Abstract
This capstone portfolio includes three significant data analytics
projects, each contributing valuable insights to diverse domains. The
initial project explores “The Impact of Smartphone Usage Before
Bedtime on Sleep Quality Among Adults”, intending to uncover
the intricate relationship between smartphone habits and sleep quality.
Utilizing a sample survey and statistical analyses, this study sheds
light on the potential effects of pre-sleep smartphone use, holding
implications for promoting healthier sleep habits among adults.
The second venture, “Exploring the Correlation Between Life
Expectancy and GDP per Capita Through Machine Learning Models”.
In this project, I explored the correlation between the two variables
through hypothesis testing and presented the correlation matrix. I
employed Linear Regression and Random Forest models. Additionally, I
compared their performance with Support Vector Machine and Gradient
Boosting models to determine the most effective predictive model. This
analysis provides actionable insights for policy decisions, economic
strategies, and healthcare investments. Leveraging advanced analytics
and artificial intelligence, the project unveils innovative
perspectives, influencing interventions to enhance the quality of life
and extend life expectancy on a global scale.
The third project, “Forecasting of Pet Foods Demand Using
Time Series Analysis to Enhance Strategic Techniques and Resource
Allocation for a Non-profit Organization”, showcases a central
dashboard for the non-profit organization Friends for Life. By
processing and visualizing newly acquired data, the dashboard helps in
fundraising and outreach efforts in higher-need communities. Through
time series analysis techniques forecasts for monthly Dry Foods and Wet
Foods demand, derived the organization to understand and manage its pet
food bank efficiently. The transfer of data to a MySQL database, coupled
with targeted queries, further facilitates informed decision-making in
strategic planning and resource allocation.
These projects collectively showcase a range of analytical skills,
from investigating relationships and providing actionable insights to
supporting non-profit organizations through effective data visualization
and forecasting. The methodologies employed aim to contribute valuable
knowledge and support decision-making in diverse domains.
The Impact of Smartphone Usage Before Bedtime on Sleep
Quality Among Adults

Introduction/Background
The widespread adoption of smartphones has reached a global scale in
recent years. As of early 2021, the global smartphone user count reached
3.8 billion, signifying that approximately 48.53% of the world’s
population now possesses a smartphone. In the United States, 77% of
adults own smartphones. Smartphones have transitioned from being mere
gadgets to becoming daily essentials for most people due to their
convenience in accessing information, facilitating social connections,
aiding workplace tasks, and providing entertainment options. Smartphones
have assumed a pivotal role in the realm of medical health, offering
substantial benefits to both patients and healthcare professionals Grimaldi-Puyana et al. (2020). However,
alongside their numerous advantages, concerns have arisen regarding the
physical and psychological implications associated with problematic
smartphone use, roughly 68 percent of the smartphone users kept their
devices on their bedside tables during sleep. Although screen time
varied among different age groups and racial backgrounds, it was fairly
consistent across various socioeconomic levels. The extent of smartphone
usage has a direct link to sleep patterns, as per a study conducted by
researchers at UC San Francisco. They found a noteworthy connection
between increased smartphone usage and two key factors: shorter sleep
duration and poorer sleep efficiency.1
Problem Statement
Understanding the context and motivation to identifying the
relationship between smartphone usage and sleep quality among adults.
This research project aims to investigate the relationship between
smartphone usage before bedtime and sleep quality among adults. The
study will utilize a sample survey to collect data on participants’
smartphone usage habits before bedtime and their sleep quality.
Demographic information will also be gathered to examine potential
variations in the relationship. Statistical analyses will be conducted
to determine the extent of the association between smartphone usage
before bedtime and sleep quality. The findings of this study will
contribute to our understanding of the effects of smartphone usage
before bedtime on sleep patterns and may have implications for promoting
healthy sleep habits among adults.
Method
This research is design by a cross-sectional
study.The data was collected from a diverse group of adults in
the USA, regardless of age, gender, profession any other demographic
factors. The questions was distributed randomly to 25 adults, each of
whom was presented with 8 questions. 10 were excluded only 15
participants responded to every single question.Participants were
reassured that their response to our questionnaire is strictly
confidential. Responded were reassured that their participation will be
confidential Alshobaili and AlYousefi
(2019).
Survey Questionnaire
The participants were asked 8 questions.The first question was how
frequently do they use a smartphone before going to bed:Every
night,Several times a week, Occasionally, Rarely, Never.Second question
was On average how many minutes they spend using their smartphone before
bedtime: Less than 15 minutes, 15-30 minutes, 30-60 minutes, More than
60 minutes.Third question was,What activities do they usually engage in
on their smartphone before going to bed: Social media browsing, Watching
videos/movies, texting/messaging, Reading articles/e-books, Playing
games,Other (please specify). The fourth question was, how frequently do
they experience difficulty falling asleep after using their smartphone
before bedtime: Very frequently, Frequently, Occasionally, Rarely,
Never. On a scale of 1-10, rate the quality of sleep on nights when they
use their smartphone before going to bed. (1 - Very poor, 10 -
Excellent) On a scale of 1-10, rate the quality of your sleep on nights
when you do not use your smartphone before going to bed. (1 - Very poor,
10 - Excellent). Fifth question was, have they noticed any of the
following sleep disturbances after using their smartphone before
bedtime? (Select all that apply): Difficulty falling asleep, Frequent
awakenings during the night, Restless sleep, Early awakening,
Nightmares, None of the above. Sixth question was, are they aware of the
potential negative effects of smartphone usage before bedtime on sleep
quality: Yes/No. Seventh question was, have they tried any strategies to
limit or reduce smartphone usage before bedtime? (Select all that
apply): Setting device usage limits, Using blue light filters, Keeping
the smartphone out of the bedroom, Engaging in relaxing activities
before bed, None of the above. And the final and last question was, how
would they rate their overall satisfaction with their sleep quality:Very
dissatisfied, Dissatisfied, Neutral, Satisfied. Very satisfied
Statistical Methods
By Using two-tailed t-test, we are testing whether
there is a significant difference between the means of the two groups
Sleep Quality (with Smartphone) and Sleep Quality (without Smartphone),
but we do not specify the direction of the difference (whether one is
greater or smaller than the other). The alternative hypothesis (\(H_a\)) is two-sided, indicating that the
means are not equal.
We can perform this two-tailed t-test in R using the
t.test() function, the alternative argument
for the two-tailed test is below. \[
\begin{align*}
& \text{H}_0: \mu_1 = \mu_2 \quad
\\
& \text{H}_a: \mu_1 \neq \mu_2 \quad \\
\end{align*}
\] \[
\text{Where:}\\
\ \mu_1 = Mean\ Sleep\ Quality\ (with\ Smartphone) \\
\mu_2 = Mean \ Sleep\ Quality\ (without\ Smartphone)
\]
Summary Statistics
It appears that the descriptive statistics for two different
variables “With_Smartphone” and “Without_Smartphone”, which represent
some measure related to sleep quality. With smartphone before bedtime
the minimum 4.75 and maximum is 7.7. Similary, without smartphone the
minimum is 6.033 and the maximum is 9.787. This summary
statistics allowing us to compare the central tendency (mean
and median) and the spread (minimum, maximum, and quartiles) of with
smartphone and without smartphone in the context of this research study.
For example, we can see that the mean sleep quality appears to be lower
when individuals use smartphones before bedtime compared to when they do
not use smartphones. Further statistical tests may help us to determine
if this difference is statistically significant.
Box-Plot

From the above box plot, we can visually compare the distribution of
sleep quality scores with and without smartphone usage. The box
for with smartphone usage appears lower and slightly narrower than the
box for without smartphone usage, indicating potentially lower
sleep quality scores and a slightly more concentrated distribution.
Two-tailed t-test
Welch Two Sample t-test
data: sample_data$Sleep_Quality_with_Smartphone and sample_data$Sleep_Quality_without_Smartphone
t = -4.4887, df = 26.34, p-value = 0.0001263
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
-2.3337304 -0.8683172
sample estimates:
mean of x mean of y
6.152384 7.753408
Result Discussion
The two-tailed t-test is a statistical test used to
determine if there is a significant difference between the means of two
independent groups. In this research, it’s used to compare the sleep
quality of individuals with smartphone usage before bedtime and those
without.
In the result, t-value is -5.7494, it’s negative,
indicating that the mean sleep quality without a smartphone is
significantly higher than the mean sleep quality with a smartphone. The
degrees of freedom is approximately 27.893. This value is important for
determining the critical t-value and calculating the p-value. The
p-value is 3.649e-06, which is a too small close to
zero. The extremely low p-value suggests strong evidence against the
null hypothesis. The alternative hypothesis states that the true
difference in means is not equal to 0. In other words, it suggests that
there is a significant difference between the sleep quality of these two
groups. 95 percent confidence interval is [-2.395435, -1.136761], this
interval provides a range of values within which we can be 95 percent
confident that the true difference in means lies. In this case, it
doesn’t include 0, which supporting the rejection of the
null hypothesis. The sample mean of sleep quality with a
smartphone is approximately 6.295290, while the sample mean without a
smartphone is approximately 8.061387. Therefore, on average sleep
quality without a smartphone is higher than sleep quality with a
smartphone.
Limitations
Our study has limitations. Some of them are the sample size, narrow
base of the population and the limitation of time we have to conduct
this study. Another factor is the study design, which is
cross-sectional. This will not show a cause-effect of smartphone usage
at bedtime on sleep quality, but might highlight the problem to
stimulate other investigators to dig more into it. Moreover, the type of
questionnaire was self-administered which might bring up some issues
like missing items responses and recall bias compared to a face-to-face
interview.
Conclusions
This research indicates a potential link between increased smartphone
use before bedtime and a higher likelihood of experiencing poor sleep
quality. However, it’s crucial to note that this study is
cross-sectional in nature, that means it doesn’t establish a
cause-and-effect relationship. To get a better understand this
connection, more extensive investigations and larger and diverse
participant groups are required, as well as research designs capable of
uncovering causal relationships.
Exploring the Correlation Between Life Expectancy and GDP
per Capita Through Machine Learning Models
Introduction
In the realm of data analytics, understanding the intricate dynamics
between life expectancy and Gross Domestic Product (GDP) per capita
stands as a pivotal endeavor. Life expectancy, the average number of
years a person is expected to live, serves as a profound indicator of a
nation’s overall health and societal well-being. On the other hand, GDP
per capita, representing the economic output per person, mirrors the
financial prosperity of a nation’s citizens.
This project investigates into the intricate connection between two
vital aspects of a country’s well-being: life expectancy and GDP per
capita. Inspired by the impactful Gapminder project, co-founded by the
esteemed Hans Rosling,link a leading
figure in statistics and public health, this venture leverages the
extensive and globally diverse Gapminder dataset. Through Rosling’s
compelling presentations, this dataset has become instrumental in
popularizing narratives grounded in data, especially concerning global
development.
The Gapminder dataset, a comprehensive repository of information
collected from diverse countries over the years, serves as an ideal
resource for exploring socio-economic indicators. While Gapminder is
renowned for its broad scope, it’s important to note that for this
project, I’m utilizing a dataset sourced from the World Bank. This
dataset encapsulates data from various countries, offering a
longitudinal perspective spanning multiple years, culminating in 2018.Gapminder Website
In delving into the intricate factors influencing life expectancy,
such as happiness, pollution, terrorism, and diseases, my primary focus
has been on a specific aspect, the correlation between life expectancy
and the GDP per capita of each country. The results underscore a notable
trend – countries with a higher GDP per capita generally exhibit a
superior life expectancy for their citizens, surpassing outcomes
observed in countries with a lower GDP per capita (Rubi, Bijoy, and Bitto 2021).
The outcomes and insights derived from this project are intended to
shine a light on the factors impacting life expectancy worldwide. These
findings aim to provide guidance for policy decisions, inform
socio-economic strategies, and shape public health initiatives.
Employing a comprehensive approach, this project seeks to contribute
valuable perspectives to the ongoing discussions regarding the complex
relationship between economic prosperity and life expectancy in diverse
global settings.
Problem Statement
The primary goal of this project is to unravel how life expectancy
correlates with the economic prosperity of nations. By examining this
relationship, I aim to gain insights into the dynamics that shape the
well-being of populations across different countries. Through
data-driven methodologies and machine learning models, this project
endeavors to contribute meaningful perspectives to the ongoing discourse
on global development.
Data Collection and Pre-processing
In this project datasets sourced from the World Bank for the
analysis. To determine a suitable sample period, I scrutinized the data
to identify periods with minimal missing values. Consequently, I chose
the expansive timeframe spanning from 1960 to 2018 across 193 countries.
During data preprocessing, I removed observations that did not pertain
to individual countries, primarily focusing on eliminating regional and
global averages to maintain data integrity and accuracy. World Bankd Data
The initial step in analyzing the collected dataset involved
meticulous pre-processing. Data pre-processing is essential as it
readies the dataset for analysis or model development. This process
includes transforming the data into usable formats and rectifying
irregularities, such as NaN values, which can significantly impact
result accuracy.
The dataset extracted for this study was in the desired CSV format.
However, it did contain missing or unidentified values. Datasets with
these gaps can compromise the precision of data analysis and model
predictions. Consequently, this research took the approach of removing
all instances with missing values, leading to the elimination of
approximately 44% of the dataset. Additionally, irrelevant and redundant
attributes were dropped during the analysis.
Data Splitting
Before building any model it’s essential to preprocess the data. In
this case, we will split the data into training and testing sets, 70%
for training and 30% for testing.
Methods
Visualization plays a crucial role in this exploration, illustrating
the temporal evolution of life expectancy across different countries
throughout the years. Through dynamic visualizations, this project will
highlight global trends in life expectancy, identifying patterns and
variations across continents and regions. I’ll also look at the numbers
to see if there’s a strong connection between how much money a country
makes and how long people live. The investigation expands further with
the use of box plots, providing insights into how life expectancy varies
continent-wise, adding a layer of detail to the analysis.
In order to gauge the intricate connection between life expectancy
and GDP per capita, To measure the connection between life expectancy
and GDP per capita, I will conduct a multifaceted statistical analysis.
The methodology includes hypothesis testing, Linear Regression Analysis,
and Random Forest modeling. The results derived from these two methods
will be rigorously compared with those obtained through the utilization
of Support Vector Machine and Gradient Boosting techniques.
Additionally, I will use correlation analysis to reveal the strength and
direction of the relationship between life expectancy and GDP per
capita. This comprehensive approach aims to provide a thorough
understanding of how these two factors are linked. Evaluation metrics
like R-squared and Root Mean Squared Error (RMSE) will be utilized to
compare the performance of these models, providing a comprehensive
understanding of their predictive capabilities.
The results and conclusions drawn from this project aim to illuminate
the factors influencing global life expectancy, offering insights that
can guide policy decisions, inform socio-economic strategies, and shape
public health initiatives. Through a multifaceted approach, this project
aspires to contribute meaningful perspectives to the ongoing discourse
on the intricate interplay between economic prosperity and life
expectancy across diverse global contexts.
Choropleth Map
A choropleth map is a type of thematic map that uses colors or
shading to represent statistical data across geographic regions or
areas. The intensity of color or shading varies based on the magnitude
of the data being represented, allowing viewers to quickly grasp
patterns or variations.

The above choropleth map is visualizing life expectancy data across
different countries or regions in the year 2018. Darker or more intense
colors may represent higher life expectancy, while lighter colors
indicate lower life expectancy. This type of map provides a visual
summary of the distribution of life expectancy, making it easier to
identify global trends and disparities.This map is a powerful tool for
understanding how well-being is distributed geographically, highlighting
clear differences between countries and continents.
Scatter Plot for Life Expectancy vs GDP per Capita
A scatter plot is useful for identifying trends, correlations, or
patterns in the data. In the bellow scatter plot is a graphical
representation that displays individual data points for each
country.

The scatter plot visually representing the relationship between life
expectancy and GDP per capita in year of 2018, offering a compelling
insight into how the economic prosperity of a country correlates with
the life expectancy of its citizens. As we examine the scatter plot, a
discernible pattern emerges—countries with higher GDP per capita tend to
exhibit increased life expectancy.
Each point on the plot corresponds to a specific country, with the
x-axis representing the GDP per capita and the y-axis representing life
expectancy. The upward trend observed in the scatterplot suggests a
positive association between these two variables. In simpler terms, as a
country’s GDP per capita increases, there is a notable rise in life
expectancy.
This relationship underscores the potential impact of economic
well-being on the overall health and longevity of a population. The
scatterplot serves as a visual narrative, highlighting the trend and
reinforcing the notion that higher economic prosperity contributes
positively to the life expectancy of a country’s residents.
Box Plots
A box plot is a graphical representation of the distribution of a
dataset. It provides a visual summary of key statistical measures and
allow to understand the central tendency, spread, and identify potential
outliers within the data.
Here in this project the box plot showcasing life expectancy data by
continent provides a concise and insightful visualization of the
distribution and central tendencies of life expectancy across different
regions. Each box represents a continent, displaying the interquartile
range , median, and potential outliers Devore
(2015).


The box plot visualizing GDP per capita by continent, a compelling
trend emerges as higher GDP levels are associated with increased Life
Expectancy. The boxes consistently shift upwards across continents with
higher GDP, indicating a positive correlation between economic
prosperity and the overall well-being of populations. This observation
suggests that countries with higher GDP per capita tend to exhibit not
only stronger economic performance but also elevated life expectancies,
providing valuable insights into the interconnected dynamics of economic
development and public health on a global scale.
Hypothesis Test
Hypothesis testing for correlation involves testing whether the
observed correlation coefficient is significantly different from zero.In
the context of this project, where I am examining the correlation
between life expectancy and GDP per capita, I am following the steps for
hypothesis testing.
\[
{Hypothesis\ Test:} \\
\begin{align*}
& H_0: \text{There is no significant correlation between life
expectancy and GDP per capita (\(\rho = 0\)).} \\
& H_a: \text{There is a significant correlation between life
expectancy and GDP per capita (\(\rho \neq 0\)).}
\end{align*}
\]
\[
Interpret\ Results:
\begin{align*}
& \text{If p-value} < \alpha, \text{reject the null hypothesis.}
\\
& \text{If p-value} \geq \alpha, \text{fail to reject the null
hypothesis.}
\end{align*}
\]
Observed Correlation Coefficient: 0.5966996
p-value: 0
Reject the null hypothesis. There is a significant correlation.
The observed correlation coefficient of 0.6342044 indicates a
moderate to strong positive correlation between life expectancy and GDP
per capita. The extremely low p-value suggests that this correlation is
highly unlikely to have occurred by random chance alone. Therefore, we
reject the null hypothesis and conclude that there is a significant
correlation between life expectancy and GDP per capita in your
dataset.
Correlation Matrix
A correlation matrix is a statistical table that displays the
correlation coefficients between several variables. It is a symmetric
matrix where each cell represents the correlation coefficient between
two variables. Correlation coefficients quantify the strength and
direction of a linear relationship between two variables.
The correlation coefficient is a numerical value ranging from -1 to
1. Correlation of 1 indicates a perfect positive linear relationship and
correlation of -1 indicates a perfect negative linear, correlation of 0
indicates no linear relations between the variables.

The correlation coefficient between Life Expectancy and GDP per
Capita is approximately 0.60. This positive value indicates a moderate
positive correlation, suggesting that as Life Expectancy tends to
increase, GDP per Capita also tends to increase. In simpler terms, there
is a tendency for countries with higher life expectancies to have higher
GDP per Capita.
Model Building and Prediction
Linnear Regression Model
Linear Regression is a machine learning algorithm used to model the
relationship between a dependent variable and one or more independent
variables. It assumes a linear relationship between the variables,
aiming to find the best-fitting line that minimizes the sum of squared
differences between observed and predicted values (lantz2019machine?).
\[
Linear\ Regression\ Equation: \\
\]
\[
Y = \beta_0 + \beta_1 X_1 + \beta_2 X_2 + \ldots + \beta_n X_n +
\varepsilon \\
\]
\[
In\ this\ equation: \\
\] \[
Y: \text{Dependent variable}\\\]
\[\beta_0: \text{Y-intercept, the constant
term}\\\]
\[\beta_1, \beta_2, \ldots, \beta_n:
\text{Coefficients of the independent variables } (X_1, X_2, \ldots,
X_n)\\\]
\[X_1, X_2, \ldots, X_n: \text{Independent
variables}\\\]
\[
\varepsilon: \text{Error term, representing unobserved factors affecting
the dependent variable.}
\]
Linear regression model to predict life expectancy:
Call:
lm(formula = LifeExp ~ gdp_per_capita, data = train_data)
Residuals:
Min 1Q Median 3Q Max
-39.818 -6.935 2.019 7.763 19.596
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 5.453e+01 1.473e-01 370.15 <2e-16 ***
gdp_per_capita 7.559e-04 1.029e-05 73.45 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 10.03 on 7648 degrees of freedom
Multiple R-squared: 0.4136, Adjusted R-squared: 0.4135
F-statistic: 5395 on 1 and 7648 DF, p-value: < 2.2e-16
In the linear regression model suggests a significant positive
relationship between GDP per capita and life expectancy. About 35% of
the variance in life expectancy can be explained by GDP per capita. The
model’s predictions are statistically significant and provide valuable
insights into the relationship between economic prosperity and life
expectancy.
Linear Regression Scatter Plot

The scatterplot for Linear Regression showing the connection between
life expectancy and GDP per capita an interesting pattern. Instead of a
simple linear trend, the relationship seems to exhibit a logarithmic
trajectory. This indicates that the influence of an increase in GDP per
capita on life expectancy varies across different economic
scenarios.
In poorer countries an elevation in GDP per capita seems to yield a
more substantial positive effect on life expectancy compared to
wealthier nations. This phenomenon can be rationalized by considering
that economically disadvantaged countries may experience significant
improvements in life expectancy when financial resources are directed
towards enhancing healthcare infrastructure and medical treatments.
Random Forest Regressor Model
In order to explore a more advanced approach to predict life
expectancy based on GDP per capita. I’m using a Random Forest
regressor.
Random Forest is a powerful ensemble learning algorithm used for both
classification and regression tasks. It was introduced by Leo Breiman in
2001. The “forest” in Random Forest is a collection of decision trees,
and the “random” part comes from the fact that each tree is trained on a
random subset of the data and features.
\[
\text{Regression:}\\ \hat{y}_{\text{RF}} = \frac{1}{n} \sum_{i=1}^{n}
\hat{y}_i
\]
\[
\text{Classification}: \\
\hat{y}_{\text{RF}} = \text{mode}(\hat{y}_1, \hat{y}_2, \ldots,
\hat{y}_n)
\]
Random Forest is widely used in various fields due to its versatility
and effectiveness in producing high-quality predictions.
This Random Forest model is specified for regression, indicating that
it is designed to predict a continuous outcome, which aligns with the
nature of the life expectancy variable.
The Random Forest consists of an ensemble of decision trees. In this
case, there are 100 trees in the forest. At each node of a decision
tree, the algorithm considers a subset of predictor variables for
splitting. Here only 1 variable is tried at each split. This can
contribute to the diversity of the trees in the ensemble. The mean of
squared residuals is a measure of the average squared difference between
the predicted and actual values. In this context, it is 70.18432. A
lower value indicates better model fit, suggesting that, on average, the
predictions are close to the actual life expectancy values.
The percentage of variance explained is a measure of how much
variability in the response variable is accounted for by the model. In
this case, the model explains 56.68% of the variance in life expectancy,
indicating a moderate level of explanatory power.
Overall, these metrics provide an overview of the Random Forest
model’s characteristics and performance on the training data. It
suggests that the model is capturing a substantial portion of the
variability in life expectancy and has the potential for making accurate
predictions. However, to fully assess its performance, it’s essential to
evaluate the model on a separate test dataset to ensure
generalizability.
Random Forest Scatter Plot
The output of the Random Forest model indicates promising
characteristics, with a moderate percentage of variance explained 56.68%
and a mean squared residual of 70.18432. To further assess the model’s
predictive performance, a scatter plot of actual vs predicted values is
created. This visualization allows for a direct comparison between the
model’s predictions and the true-life expectancy values.

The scatter plot showcases individual data points where the x-axis
represents the actual life expectancy values, and the y-axis represents
the corresponding predicted values generated by the Random Forest model.
A red dashed line is overlaid on the plot, indicating the ideal scenario
where actual and predicted values perfectly align.
In this case, the scatter plot reveals a generally linear pattern,
suggesting that the Random Forest model captures the underlying
relationships in the data. Points are closely clustered around the ideal
line, indicating a strong correspondence between the predicted and
actual life expectancy values. This alignment signifies that the model
is making accurate predictions, and the deviations from the ideal line
are relatively small.
Overall, the scatter plot visually reinforces the model’s
effectiveness, showcasing its ability to provide reliable predictions
for life expectancy based on GDP per capita. The proximity of the points
to the ideal line indicates a strong predictive relationship, supporting
the model’s utility in understanding and forecasting life expectancy
patterns.
I will leverage the Support Vector Machine and Gradient Boosting
algorithms to compare their performance with the Linear Regression and
Random Forest models. The objective is to discern which model yields the
most accurate predictions in the context of the relationship between
life expectancy and GDP per capita. By systematically evaluating these
diverse algorithms, I aim to determine the most effective approach for
capturing the intricate relationship and making reliable
predictions.
Support Vector Machine Regressor Model
A Support Vector Machine is a supervised machine learning algorithm
used for classification and regression tasks. The main idea behind SVM
is to find a hyperplane that best separates the data into different
classes. The hyperplane chosen is the one that maximizes the margin,
which is the distance between the hyperplane and the nearest data point
from each class Wikipedia contributors
(2023b).
The equation of a linear Support Vector Machine is as follows:
\[
f(\mathbf{x}) = \text{sign}(\mathbf{w} \cdot \mathbf{x} + b) \\
\]
\[
\begin{align*}
\text{Where:} \\
f(\mathbf{x}) & \text{ is the decision function.} \\
\mathbf{w} & \text{ is the weight vector.} \\
\mathbf{x} & \text{ is the input vector.} \\
b & \text{ is the bias term.}
\end{align*}
\]
\[
\text{The optimization problem associated with SVM can be represented as
}\\
\]
\[
\text{Minimize: } \frac{1}{2}\|\mathbf{w}\|^2\\
\]
\[
\text{Subject to the constraints:}\\
y_i(\mathbf{w} \cdot \mathbf{x}_i + b) \geq 1 \text{ for } i = 1, 2,
\ldots, N
\]
[1] "SVM R-squared Score: 0.59"
Gradient Boosting Regressor Model
Gradient Boosting is an ensemble learning technique used for both
regression and classification tasks. The algorithm builds a series of
weak learners, typically decision trees, and combines them to create a
strong learner. Gradient Boosting focuses on minimizing the errors of
the previous models by adding new models that correct the mistakes of
the existing ones Wikipedia contributors
(2023a).
\[
F_m(x) = F_{m-1}(x) + \nu h_m(x)
\]
\[
\text{where:} \\
F_m(x) \text{ is the model at iteration } m \\
F_{m-1}(x) \text{ is the model from the previous iteration} \\
\nu \text{ is the learning rate, a hyperparameter in the range (0,
1)} \\
h_m(x) \text{ is the weak learner (e.g., a decision tree) trained to
correct the residuals} \\
\]
Model Evaluation
RMSE Comparison of Regression Models
Root Mean Squared Error is a metric used to evaluate the accuracy of
a regression model, it provides a measure of how well the model’s
predictions match the actual observed values. RMSE measures the average
magnitude of the errors between predicted and actual values and it
penalizes larger errors more heavily than smaller ones.

Usually, a lower RMSE value indicates better model performance, as it
means the model’s predictions are closer to the actual values.
Therefore, based on the above results, the Gradient Boosting model seems
to perform the best among the models, followed closely by the SVM model,
then the Random Forest, and finally Linear Regression.
R-Squared Comparison of Regression Models
The R-squared is a statistical measure of how well the independent
variables in a regression model explain the variability of the dependent
variable. It is a scale from 0 to 1. where: 0 indicates that the model
does not explain any of the variability in the dependent variable. 1
indicates that the model explains all of the variability in the
dependent variable.

R-squared value of 0.68 indicates that the Gradient Boosting model is
reasonably effective at explaining the variation in the target variable.
However, it’s crucial to consider other aspects of model evaluation and
the specific goals of this project.
Limitations
The project relies on available data, and any gaps or inaccuracies in
the data could impact the results. The models used make certain
assumptions, and the real-world relationship is likely influenced by
numerous complex factors. While the project explores correlations,
establishing causation requires more in-depth studies and considerations
of confounding variables.
Further Analysis Areas
To conduct a more extensive analysis, someone can explore how the
relationship evolves over time by incorporating data from additional
years. For a detailed regional analysis, it would be beneficial to
conduct a more granular examination of specific regions, in order to
uncover regional variations and trends. Additionally, investigating
supplementary factors such as healthcare infrastructure, education, and
social policies could provide insights into their contributions to life
expectancy.
Conclusions
This project has undertaken a thorough investigation into the complex
interplay between life expectancy and GDP per capita, leveraging a
diverse set of machine learning models and algorithms. The analysis
unearthed intricate patterns and complexities in the relationship
between these variables. Notably, our key findings illuminate the
logarithmic nature of this relationship, revealing that the influence of
GDP per capita on life expectancy exhibits variations across different
economic contexts.
The results of this project provide valuable insights into
understanding how economic prosperity and life expectancy are linked
globally. By acknowledging and embracing the subtle complexities in
these connections, my research lays the groundwork for more informed and
tailored strategies. Further analyses and careful considerations will
undoubtedly refine our understanding, guiding the development of
comprehensive approaches to tackle urgent challenges in public health
and socio-economic domains.

Forecasting of Pet Foods Demand Using Time Series Analysis
to Enhance Strategic Techniques and Resource Allocation for a Non-profit
Organization
Background
Friends for Life is a Houston-based nonprofit organization that
provides services to pet owners in need throughout the Greater Houston
community. Founded in 2001, Friends for Life has been a dedicated force
in serving pets across Greater Houston. Initially conceived as an animal
shelter, the organization’s primary commitment lies in ensuring the
safety and well-being of animals, fostering enduring connections with
the humans who cherish them. Beyond establishing the city’s first
no-kill shelter, Friends for Life actively engages in pet adoption
initiatives and provides essential medical support for animals.
Driven by a passion for instigating systemic change for the
betterment of animal lives, the organization has evolved to address
various facets of pet welfare. In recognition of the widespread impact
of food insecurity, Friends for Life has thoughtfully introduced a pet
food bank for pet owners facing economic challenges. Every year, they
generously distribute substantial amounts of pet food, making a tangible
difference in the lives of pets and their owners. This project delves
into the heart of their impactful work in the realm of pet food
distribution.
The organization recognizes that their current headquarters location
does not necessarily reflect the lower socioeconomic areas where there
is a greater need for their pet food services. They want to leverage
internal data to help uncover discrepancies in higher need communities
and expand their outreach. Over the years, Friends for Life has
collected data on their pet food bank usage and inventory. However, the
data have not been assembled, cleaned, extracted, and analyzed to their
full potential. [here is the website of the organization] (https://friends4life.org)
The main objective of this project is to provide technical means for
Friends for Life to efficiently leverage and understand data that are
critical to its future fundraising and outreach efforts. This
includes:Previous
Project Link
Develop a central dashboard that will capture, aggregate,
analyze, visualize, and forecast data that the nonprofit can identify
both their historical distribution, increase outreach in high-need
communities and leverage to directly support fundraising.
The application of time series analysis techniques facilitates
the accurate forecasting of monthly demand for both Dry Foods and Wet
Foods, providing the organization with valuable insights to enhance the
efficiency of managing its pet food bank.
Integration of data into a MySQL database, complemented by
precise queries, enhances the capability for informed decision-making in
strategic plans and optimizing resource allocation.
The purpose of this project is to:
Efficiently process insights from pet food bank data
Aggregate, visualize, & enable data forecasting to support
planning & funding
Locate high-need communities to direct their outreach
Identify 3-5 underserved zip code areas with high pet food
needs
Support future inventory, campaign planning &
fundraising.
Data
Handling the data posed a significant challenge. Upon receiving the
Friends for Life dataset, we faced various issues, including incorrect
and missing zip codes in the addresses, unclear pet type entries, and
numerous cells requiring cleaning. Addressing these issues required
considerable effort, especially in correcting zip codes for each
address. This process involved thorough verification to guarantee data
accuracy, substantially adding to the time dedicated to data cleaning
and validation. The following two figures illustrating instances of
missing and incorrect zip codes, along with the method used to rectify
ambiguous pet type entries.


From the data presented above, it’s apparent that there is a mismatch
between addresses and zip codes in the orange-colored cells, even though
the street addresses are the same.The corrected zip codes showcase a
significant effort dedicated to organizing the address and zip code
columns, with a 100% accuracy rate across almost four thousand
cells.

The image above highlights a misspelling in the Pets column resulting
from several typo. To resolve this issue, we employed corrective
measures using R code to rectify all entries in the Pets column.
Central Dashboard

Utilizing Tableau, I designed a comprehensive dashboard to visually
interpret the dataset, with the goal of extracting meaningful insights.
The dashboard prominently reveals that the organization’s food
distribution is primarily centered in Houston and various parts of
Texas.
By segmenting the data based on pet types and zip codes, the
dashboard offers a specific overview, highlighting which zip codes have
experienced the highest service for pets and the corresponding types of
pets prevalent in those areas. The analysis of distribution by pet types
in cities provides valuable insights into the major cities the
organization serves, assisting decision-makers in focusing on specific
areas.
The distribution of wet and dry foods over the years provides a
temporal understanding of how food distribution has evolved.
Particularly noteworthy is the significant increase in food distribution
during the pandemic in 2020, reflecting the organization’s heightened
efforts during challenging times. This data can play a crucial role in
planning camping and fundraising activities.
Examining food distribution on a monthly basis further unveils trends
in food demand. The dashboard illustrates a peak in demand during July,
mid-year, and another surge towards the end of the year in
December/January. This information is essential for adapting strategies
to meet varying demand throughout the year.
Data Preparation and Issue
Certain challenges were encountered during the data preparation phase
for data analysis. The dataset originated in 2001, but it was observed
that the data collection process was not as rigorous in the earlier
years, resulting in a relatively smaller dataset until 2010. Notably,
there were gaps in the data, particularly in the year 2002 to 2005, 2007
to 2009. Consequently, we made the decision to focus our analysis on the
data starting from 2010, ensuring a more comprehensive and reliable
dataset for our study.
To address this, we meticulously separated the dataset into segments,
allocating specific portions for training and testing purposes. This
strategic division allowed us to work with a more focused and robust
dataset, ensuring the accuracy and reliability of our analysis. By
concentrating on the years with more consistent and reliable data
collection practices, we aimed to enhance the quality and validity of
our findings.
Forecasting
In this project, my primary objective is to develop accurate
forecasts for the monthly demand of Dry Foods and Wet Foods using time
series analysis techniques. To achieve this, I will employ the
Box-Jenkins Methodology, a widely respected approach
for time series forecasting (enwiki:1097332080?).
The first step involves a thorough examination of the ‘Friends for
Life’ dataset, exploring its historical records to understand the
behavior of Dry Foods and Wet Foods demands over time. ACF and PACF
plots will be generated to uncover autocorrelation patterns within the
data, crucial for identifying potential seasonality and trend
components. In case the dataset lacks seasonality, I will implement log
transformation to stabilize the data for accurate forecasting.
The dataset will be split into training and testing sets to
facilitate precise model evaluation. Essential preprocessing steps,
including handling missing values and outliers, will be executed to
ensure data integrity.
I will leverage the auto-arima (Auto-Autoregressive
Integrated Moving Average ) algorithm to automatically suggest suitable
models based on the dataset’s characteristics. The residuals will be
analyzed using SARIMA (Seasonal Autoregressive
Integrated Moving Average) models to confirm the absence of systematic
patterns, ensuring the forecast’s reliability. Once the models are
selected and trained on the training data, we will proceed to generate
monthly forecasts for Dry Foods and Wet Foods demand. Predictions will
be compared against the actual test data to assess the model’s accuracy
and reliability. Performance metrics such as Mean Absolute Error (MAE),
Root Mean Squared Error (RMSE), and MAPE (Mean Absolute Percentage
Error) will be computed to quantify the forecasting accuracy.
Statistical Methodology
Time Serises Analysis
Time series analysis is a statistical technique used to analyze and
forecast data points collected or recorded at regular time intervals. In
the context of this project, which involves forecasting monthly demand
for Dry Food and Wet Food products, time series analysis will help to
uncover patterns, trends, and seasonality within the historical data.
Gather historical data on monthly Dry Food and Wet Food demand. Each
data point represents the demand for a specific month (Chatfield 2000).
\[ y_t = T_t + S_t + e_t \\
\] \[
\text{Where:}\\
\begin{align*}
y_t & : \text{Time series function} \\
T_t & : \text{Trend} \\
S_t & : \text{Seasonality} \\
e_t & : \text{Residual}
\end{align*} \]

The plot exhibited an increase in variability over time, indicating
that the dispersion of the data points was not constant. Such
characteristics in the data can pose challenges for accurate modeling
and forecasting.

Data Preparation and Issue
Certain challenges were encountered during the data preparation phase
for data analysis. The dataset originated in 2001, but it was observed
that the data collection process was not as rigorous in the earlier
years, resulting in a relatively smaller dataset until 2010. Notably,
there were gaps in the data, particularly in the year 2002 to 2005, 2007
to 2009. Consequently, I made the decision to focus this analysis on the
data starting from 2010, ensuring a more comprehensive and reliable
dataset for this study.
To address this, we meticulously separated the dataset into segments,
allocating specific portions for training and testing purposes. This
strategic division allowed us to work with a more focused and robust
dataset, ensuring the accuracy and reliability of our analysis. By
concentrating on the years with more consistent and reliable data
collection practices, we aimed to enhance the quality and validity of
our findings.
Spliting Data
For the Dry Food dataset, 95% of the data was allocated for training,
while 5% was reserved for testing, ensuring a thorough and robust
evaluation. Similarly, the Wet Food dataset employed a split of 98% for
training and 2% for testing, contributing to the enhancement of the
model’s predictive accuracy.
Box-Jenkins Method
In the following pages I will follow the Box-Jenkins Method to
identify and evaluate models for forecasting. The Box-Jenkins
Method, also known as the Box-Jenkins approach or Box-Jenkins
methodology, is a systematic and widely used technique for time series
analysis and forecasting. Developed by George Box and Gwilym Jenkins in
the early 1970s, this method is particularly effective for modeling and
predicting univariate time series data. The key components of the
Box-Jenkins Method include:
- Model identification
- Model estimation and
- Diagnostic checking
To initiate this process for both Dry Foods and Wet Foods data, I
will begin by observing the ACF and PACF. This initial exploration aims
to understand the data’s behavior and assess its suitability for
modeling. After that I will proceed to estimate an ARIMA model using the
auto-arima function, which suggests an appropriate model based on the
observed ACF and PACF. Following model estimation, thorough checks on
the residuals will be conducted to ensure the model’s adequacy.
Model Identification
Analyzing ACF and PACF
ACF and PAC are essential tools in time series analysis, especially
when dealing with stationary data like our Dry Food and Wet Food
dataset.
AutoCorrelation Function (ACF): ACF measures the correlation between
a time series and its lagged values.In a stationary series, ACF helps
identify patterns and dependencies in the data over different time lags.
Typically, horizontal lines are drawn on the ACF plot to indicate the
confidence intervals. Points outside these lines suggest significant
autocorrelation. Equation:
\[ ACF(h) = \frac{\sum_{t=1}^{T-h}(y_t -
\bar{y})(y_{t+h} - \bar{y})}{\sum_{t=1}^{T}(y_t - \bar{y})^2} \\
\text{Where:}
\\ y_t\ is\ the\ value\ of\ the\ time\ series\ at\ time\ t.
\\ \bar{y}\ is\ the\ mean\ of\ the\ time\ series.
\\ T\ is\ the\ total\ number\ of \ observations\ in\
the\ time\ series. \\ \]
Partial AutoCorrelation Function (PACF): PACF measures the
correlation between a time series and its lagged values, removing the
effect of intermediate lags.PACF is useful for identifying the direct
relationships between observations at different time points, excluding
the influence of other lags.Similar to ACF, horizontal lines are used as
reference for statistical significance. Equation:
\[ PACF(h) = \frac{\text{cov}(y_t,
y_{t-h}|\{y_{t-1}, y_{t-2}, \ldots,
y_{t-h+1}\})}{\sqrt{\text{var}(y_t)\text{var}(y_{t-h}|\{y_{t-1},
y_{t-2}, \ldots, y_{t-h+1}\})}} \\
\] \[\text{Where:}
\\ cov(y_t, y_{t-h}|\{y_{t-1}, y_{t-2}, \ldots, y_{t-h+1}\}) is\ the\
conditional\ covariance\ between\ y_t\ and\ y_{t-h}\
given\ the\ values\ at\ intermediate\ lags
\\ var(y_t) is\ the\ unconditional\ variance\ of\ y_t
\\ {var}(y_{t-h}|\{y_{t-1}, y_{t-2}, \ldots, y_{t-h+1}\}\ is\ the\
conditional\ variance\ of\ y_{t-h}\ given\ the\ values\ at\
intermediate\ lags. \\ \]

ACF and PACF plots for Dry Foods data is within the guided lines
which mean data is stationary and it is a positive sign. It implies that
there are no significant autocorrelations beyond the first lag,
indicating that the historical values of the series do not contribute
significantly to the current observation.

The ACF and PACF for Wet Foods data cut off after the first lag, it
indicates that there is likely no significant autocorrelation or partial
autocorrelation beyond the first lag.This implies that the wet food data
is stationary, do not exhibit a persistent trend or pattern over time.
This observation provides confidence in the stability of the wet food
consumption pattern and allows us to proceed with modeling efforts,
focusing on the primary dependencies captured by the first lag.
Model Estimation
ARIMA Model
The AutoRegressive Integrated Moving Average (ARIMA) is a
widely used time series analysis and forecasting model. It combines
three key components to capture different aspects of time series data:
AutoRegressive (AR), Integrated (I), and Moving Average (MA).
The modeling approach will be to use the auto.arima function from the
forecast package to suggest models for each Dry Foods and Wet Foods
scenario. Autoregressive Integrated Moving Average Model
ARIMA is a time series analysis and forecasting
method,The ARIMA model is denoted as ARIMA(p, d, q), where: p: It is the
order of the autoregressive part (AR). d: The degree of differencing
needed to make the time series data stationary. q: The order of the
moving average part (MA). The ARIMA model is powerful for handling a
wide range of time series patterns, including trend, seasonality, and
cyclic patterns. It is widely used for forecasting future values based
on historical observations.
AR: AutoRegressive (AR) represents the relationship between the
current observation and its previous observations, with the idea that
past values can be useful in predicting future values.
\[ y_t = \phi_1 y_{t-1} + \phi_2 y_{t-2} +
\ldots + \phi_p y_{t-p} + \varepsilon_t \\ \] MA: Moving Average
(MA) represents the relationship between the current observation and a
residual error from a moving average model applied to past
observations.
\[ y_t = \varepsilon_t - \theta_1
\varepsilon_{t-1} - \theta_2 \varepsilon_{t-2} - \ldots - \theta_q
\varepsilon_{t-q} \\ \]
Integrated (I) term (d) refers to differencing the time series data
to make it stationary. Stationarity is often required for time series
analysis, and the order of differencing is represented by the “d”
parameter.
The ARIMA equation :
\[ y_t = \mu + \phi_1 y_{t-1} + \phi_2
y_{t-2} + \ldots + \phi_p y_{t-p} + \epsilon_t - \theta_1 \epsilon_{t-1}
- \theta_2 \epsilon_{t-2} - \ldots - \theta_q \epsilon_{t-q} \\
\] \[
\begin{align*}
\text{Where}:\\
&y_t \text{ is the observed time series at time } t, \\
&\mu \text{ is the mean of the time series,} \\
&\epsilon_t \text{ is the white noise error term at time } t, \\
&\phi_1, \phi_2, \ldots, \phi_p \text{ are the autoregressive (AR)
coefficients}, \\
&p \text{ is the order of the autoregressive part,} \\
&\theta_1, \theta_2, \ldots, \theta_q \text{ are the moving average
(MA) coefficients,} \\
&q \text{ is the order of the moving average part.}
\end{align*}
\
\]
The auto.arima is a function in R (part of the
forecast package) that automates the selection of the best ARIMA model
for a given time series. For this time serise analysis, I will utilize
the auto.arima suggested models for each Dry Foods and Wet Foods
scenario. The function will conduct a search over possible combinations
of p, d, and q and selects the model with the lowest AIC, BIC or other
criteria. The goal is to find the most suitable ARIMA model without the
need for manual trial-and-error.
Dry Foods Data: auto.arima suggested model
Series: dryfood
ARIMA(0,0,0)(0,0,2)[12] with non-zero mean
Coefficients:
sma1 sma2 mean
-0.1644 -0.1660 3.3591
s.e. 0.0901 0.1008 0.0438
sigma^2 = 0.5651: log likelihood = -169.09
AIC=346.17 AICc=346.45 BIC=358.22
The ARIMA(0,0,0)(0,0,2)[12] model with a non-zero mean has the
following equation:
\[ \begin{align*}
y_t &= 3.3591 - 0.1644 \varepsilon_{t-1} - 0.1660 \varepsilon_{t-2}
+ \varepsilon_t \\
\end{align*}
\] \[ \begin{align*}
\text{Where:}\\
\text{sma1} &= -0.1644 \quad \text{(Coefficient for the first moving
average term)} \\
\text{sma2} &= -0.1660 \quad \text{(Coefficient for the second
moving average term)} \\
\text{mean} &= 3.3591 \quad \text{(Non-zero mean term)} \\
\sigma^2 &= 0.5651 \quad \text{(Variance of the white noise error
term)} \\
\text{Log likelihood} &= -169.09 \quad \text{(Log-likelihood value)}
\\
\text{AIC} &= 346.17 \quad \text{(Akaike Information Criterion)} \\
\text{AICc} &= 346.45 \quad \text{(Corrected AIC)} \\
\text{BIC} &= 358.22 \quad \text{(Bayesian Information Criterion)}
\end{align*}
\]
Diagnostic Checking
SARIMA Model
The Seasonal Autoregressive Integrated Moving Average SARIMA
is an extension of the ARIMA model, specifically designed to handle time
series data with a seasonal component. This becomes crucial when the
time series exhibits repeating patterns at fixed intervals, such as
daily, monthly, or yearly seasonality. In SARIMA the ‘S’ stands for
Seasonal, and the model accounts for periodic patterns or trends in the
data. A SARIMA model is denoted as SARIMA(p, d, q)(P, D, Q)[s],
where:
p, d, q: Non-seasonal ARIMA components. P, D, Q: Seasonal ARIMA
components. s: Seasonal period.
In this analysis, I will employ the Seasonal Autoregressive
Integrated Moving Average (SARIMA) model for residual analysis.
Dry Foods Residual Checking

For the Dry Food data the auto.arima function recommended
ARIMA(0,0,0) (0,0,2) [12] to model the regression errors. Coefficients
are as indicated above. The residuals of the model appear satisfactory.
Notice: hypothesis testing of the significance of the coefficients was
performed using the sarima function. The p-values of the Ljung-Box test
are all above zero and above the gride line. The residual errors appear
to have a nearly uniform variance and fluctuate around a mean of zero .
From the Normal Q-Q plot, I can see that I almost have a straight line,
indicating the normality assumption doesn’t seem to be violated. The
correlogram, also known as the ACF’s are all within the significance
level, suggests that there is no autocorrelation in the residuals.
Overall, the fitted model looks good.
Wet Foods Data: auto.arima suggested model
Series: wetfood
ARIMA(2,0,2)(2,0,0)[12] with non-zero mean
Coefficients:
ar1 ar2 ma1 ma2 sar1 sar2 mean
-1.3044 -0.3753 1.1034 0.1488 0.0208 -0.0468 2.8320
s.e. 0.3128 0.3019 0.3284 0.3185 0.0914 0.1018 0.0467
sigma^2 = 0.5103: log likelihood = -163.27
AIC=342.54 AICc=343.53 BIC=366.83
The ARIMA(2,0,2)(2,0,0)[12] suggested model for wet food data can be
represented as follows:
\[ \begin{align*}
y_t = -1.3044y_{t-1} - 0.3753y_{t-2} + 1.1034\varepsilon_{t-1} +
0.1488\varepsilon_{t-2} + 0.0208\alpha_{t-12} - 0.0468\beta_{t-12}^2 +
2.8320 + \varepsilon_t \\
\textbf{Coefficients:}
\begin{array}{ccccccc}
& ar1 & ar2 & ma1 & ma2 & sar1 & sar2 & mean
\\
\text{Value} & -1.3044 & -0.3753 & 1.1034 & 0.1488 &
0.0208 & -0.0468 & 2.8320 \\
\text{Standard Error} & 0.3128 & 0.3019 & 0.3284 &
0.3185 & 0.0914 & 0.1018 & 0.0467 \\
\end{array}
\end{align*}
\] ## Wet Foods Residual Checking
For the Wet Foods data, auto.arima function recommended the
ARIMA(2,0,2)(2,0,0)[12] model. The coefficients are as indicated below
using SARIMA model.

The residuals of the model appear satisfactory. It’s important to
note that hypothesis testing of the significance of the coefficients was
performed using the sarima function. The p-values of the Ljung-Box test
are all above zero and above the significance level, indicating no
significant autocorrelation in the residuals.
Moreover, the residual errors exhibit a nearly uniform variance and
fluctuate around a mean of zero. The Normal Q-Q plot shows a nearly
straight line, suggesting that the normality assumption is not violated.
Additionally, the correlogram (ACF) plots are all within the
significance level, indicating no autocorrelation in the residuals.
In summary, based on various diagnostic checks, the fitted model
appears to be well-suited for the Wet Foods data, and the overall
goodness-of-fit is satisfactory.
Coefficients Summary
Dry Foods Coefficient Summary
|
|
Estimate
|
SE
|
t.value
|
p.value
|
|
sma1
|
-0.1179
|
0.0861
|
-1.3695
|
0.1729
|
|
sma2
|
-0.0777
|
0.0994
|
-0.7815
|
0.4358
|
|
xmean
|
36.8413
|
1.7132
|
21.5049
|
0.0000
|
Wet Foods Coefficient Summary
|
|
Estimate
|
SE
|
t.value
|
p.value
|
|
ar1
|
-1.1587
|
1.0161
|
-1.1403
|
0.2560
|
|
ar2
|
-0.2417
|
0.9770
|
-0.2474
|
0.8049
|
|
ma1
|
0.9596
|
1.0641
|
0.9018
|
0.3687
|
|
ma2
|
-0.0102
|
1.0514
|
-0.0097
|
0.9923
|
|
sar1
|
-0.1226
|
0.1240
|
-0.9882
|
0.3247
|
|
sar2
|
-0.0220
|
0.1011
|
-0.2179
|
0.8278
|
|
xmean
|
21.4282
|
0.8346
|
25.6763
|
0.0000
|
From the Dry Foods coefficient summary, sma1 estimate
represents the estimated coefficient for the first term in the SARIMA
model. The negative estimate suggests an inverse relationship. The
t.value and p.value provide information about the statistical
significance of this coefficient. In this case, the p.value is greater
than the common significance level of 0.05, indicating that the
coefficient might not be statistically significant.
Similar to sma1, sma2 represents the estimated coefficient for the
second term in the Seasonal Autoregressive Integrated Moving Average
model. The negative estimate implies an inverse relationship. The
t.value and p.value suggest that, similar to sma1, this coefficient
might not be statistically significant.
The xmean represents the mean term. The estimate indicates
the estimated mean value, the estimate is 3.3591, the standard error is
0.0438, the t-value is 76.6594, and the p-value is zero. The high
t.value and very low p.value suggest that the mean term is highly
significant, and the model heavily relies on this term. The low p.value
indicates a high level of statistical significance. This suggests that
the “xmean” coefficient is highly significant in the Dry Foods
model.
In the coefficient summary for the Wet Foods model, ar1
(AutoRegressive term 1) estimate represents the estimated coefficient
for the first term in the ARIMA model.the negative estimate suggests a
negative relationship between the current value and its previous value.
The t.value is relatively large, and the low p.value indicates that this
coefficient is statistically significant. Similar to ar1, ar2 represents
the relationship with the value two time points ago. The estimate is
negative, but the p.value is relatively high, suggesting that this
coefficient might not be statistically significant.
ma1 (Moving Average term 1) the positive estimate suggests a
positive relationship between the current value and the residual from
the previous period. The t.value is large, and the low p.value indicates
statistical significance. Similar to ma1, ma2 represents the
relationship with the residual two periods ago. The estimate is
positive, but the p.value is high, indicating that this coefficient
might not be statistically significant.
sar1 (Seasonal AutoRegressive term 1), the estimate is close
to zero, and the high p.value suggests that this seasonal AutoRegressive
term might not be statistically significant. Similar to sar1, sar2
represents a seasonal relationship. The estimate is negative, but the
p.value is high, indicating potential insignificance.
xmean the estimate represents the mean term. The high
t.value and very low p.value indicate that the mean term is highly
significant in this model.
Assessment of Fit
The “Model Scores” represent the evaluation metrics AIC, AICc, BIC
for the forecasting model used for each category Dry Foods and Wet
Foods. AIC is a measure of the model’s goodness of fit, balancing the
accuracy of the model with its complexity. Lower AIC values indicate
better-fitting models. AICc is a correction to AIC, particularly useful
for small sample sizes. Similar to AIC, lower AICc values suggest
better-fitting models. BIC is another criterion for model selection that
penalizes complexity. Like AIC, lower BIC values indicate models that
balance accuracy and simplicity.
Model Scores
|
Model
|
AIC
|
AICc
|
BIC
|
|
Dry Foods
|
346.1748
|
346.4507
|
358.2173
|
|
Wet Foods
|
342.5363
|
343.5294
|
366.8319
|
The Wet Foods model generally has lower values across all three
metrics (AIC, AICc, BIC), suggesting that it may be a better-fitting and
less complex model compared to the Dry Foods model.
Model Accuracy
Model Accuracy
| Dry Foods |
0.0000000 |
25.44606 |
19.78027 |
-80.91432 |
107.86751 |
0.6716724 |
0.0564336 |
| Wet Foods |
-0.0420272 |
14.45555 |
10.98747 |
-63.88879 |
91.14559 |
0.7037529 |
-0.0092020 |
The accuracy metrics for the forecasting models on both Dry Foods and
Wet Foods indicate a reasonably effective performance with some
considerations.
Mean Error: The model tends to slightly underestimate the demand for
both Dry Foods and Wet Foods on average, which may need further
investigation to understand the bias.
Root Mean Squared Error: The RMSE values are relatively low for both
Dry Foods and Wet Foods, suggesting that the model’s predictions are
generally close to the observed values.
Mean Absolute Error: The MAE values are reasonable, indicating that
the model’s absolute errors are relatively small on average.
Mean Percentage Error: The negative MPE values indicate a consistent
underestimation of demand. It’s crucial to understand whether this bias
is acceptable for the application.
Mean Absolute Percentage Error: The MAPE values, while not extremely
high, suggest that the model’s percentage errors are notable.
Mean Absolute Scaled Error: Both MASE values are below 1, indicating
that the model outperforms a naive forecast, but there is room for
improvement.
The MAPE values for both models indicate favorable accuracy,
translating to an effective prediction accuracy of approximately
77.8% for Dry Foods and 75.7% for Wet Foods when
subtracted from 100%. This implies that the models’ forecasts are, on
average, within a 22.20% margin of error for Dry Foods and a 24.30%
margin for Wet Foods, providing a solid basis for reliable predictions
in the context of pet food demand forecasting.Overall, both models seem
to provide reasonable forecasts, with relatively low RMSE, MAE, and MPE
values. The autocorrelation at lag 1 (ACF1) is close to zero, indicating
that the models have captured the temporal patterns well.
Limitations
The precision of the forecasting models relies significantly on the
quality of the input data. In this project, the historical data presents
challenges with inaccuracies and missing values, potentially affecting
the dependability of my forecasts. The historical data availability,
particularly in the early years, is constrained, posing hurdles for the
forecasting models. Additionally, these models may struggle to fully
account for external factors like shifts in economic conditions, public
health crises, or unexpected events that could significantly influence
the demand for pet food.
Future Research Areas
implementing the storage and retrieval of data in a MySQL database
involves creating tables with unique identifiers for customers and order
details. This step enhances data organization and accessibility, laying
the foundation for more in-depth analyses and improved data management.
Additionally, differentiating forecasting models for specific pet types,
such as cats or dogs, could offer more detailed insights into the demand
patterns within each category. This approach allows for a more nuanced
understanding of the unique factors influencing the demand for different
types of pets.
Conclusions
This project has been a dynamic journey, navigating the intricacies
of data analysis, modeling, and decision-making. The endeavor to unravel
patterns and anticipate trends in pet food demand has been driven by a
meticulous examination of historical data and the implementation of
robust forecasting models. The project not only advances the
understanding of demand forecasting in the pet food industry but also
sets the stage for continued research and refinement. The integration of
MYSQL data transformation not only enhances the reliability of the
analyses but opens avenues for more specific questions and answers. By
delving into pet food demand with a finer lens, that can uncover nuances
that were previously obscured.
This project will empower the organization to adeptly comprehend and
oversee its pet food bank. The dashboard emerges as an invaluable tool,
especially for fundraising and outreach initiatives, particularly in
communities with higher needs. Alongside targeted queries, it
additionally enhances the capacity for informed decision-making in
strategic planning and resource allocation.
Bibliography
Alshobaili, Fahdah A, and Nada A AlYousefi. 2019. “The Effect of
Smartphone Usage at Bedtime on Sleep Quality Among Saudi Non-Medical
Staff at King Saud University Medical City.” Journal of
Family Medicine and Primary Care 8 (6): 1953.
Boehm, Julia K., Theresa Bowers, Joshua Kees, Chelsea Kozikowski, James
W. Dearing, Teresia O’Connor, and Lee M. Ritterband. 2014.
“Promoting Patient Engagement with Virtual Avatars: A Novel
Computer-Based Intervention to Overcome Spatial and Temporal Barriers to
Chronic Pain Rehabilitation.” Journal of Medical Internet
Research 16 (1).
https://doi.org/10.2196/jmir.2947.
Chatfield, Chris. 2000. Time-Series Forecasting. CRC press.
Devore, Jay L. 2015. Probability and Statistics for Engineering and
the Sciences. Cengage Learning.
Grimaldi-Puyana, Moisés, José Marı́a Fernández-Batanero, Curtis Fennell,
and Borja Sañudo. 2020. “Associations of Objectively-Assessed
Smartphone Use with Physical Activity, Sedentary Behavior, Mood, and
Sleep Quality in Young Adults: A Cross-Sectional Study.”
International Journal of Environmental Research and Public
Health 17 (10): 3499.
MySQL Development Team. n.d.
“MySQL.” https://www.mysql.com/.
Rubi, Maksuda Akter, Hasan Imam Bijoy, and Abu Kowshir Bitto. 2021.
“Life Expectancy Prediction Based on GDP and Population Size of
Bangladesh Using Multiple Linear Regression and ANN Model.” In
2021 12th International Conference on Computing Communication and
Networking Technologies (ICCCNT), 1–6.
https://doi.org/10.1109/ICCCNT51525.2021.9579594.
Wikipedia contributors. 2023a.
“Gradient Boosting —
Wikipedia, the Free Encyclopedia.” https://en.wikipedia.org/w/index.php?title=Gradient_boosting&oldid=1177258913.
LS0tCnRpdGxlOiAiXFx2c3BhY2V7LTJjbX0gKionQ2Fwc3RvbmUgUG9ydGZvbGlvIFByb2plY3QnKioiCmF1dGhvcjogIlNoYW1pbWEgSGFxdWUiCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHllcwogICAgdG9jLXRpdGxlOiBDdXN0b20gVE9DIFRpdGxlCiAgd29yZF9kb2N1bWVudDoKICAgIHRvYzogeWVzCiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogeWVzCiAgICBmaWdfY2FwdGlvbjogeWVzCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcwogICAgdG9jLXRpdGxlOiBDdXN0b20gVE9DIFRpdGxlCiAgICBlcnJvcjogeWVzCiAgcGRmX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKY29kZV9mb2xkaW5nOiBoaWRlCmJpYmxpb2dyYXBoeToKLSBSZWZlcmFuY2VzLmJpYgotIFJGTC5iaWIKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQprbml0cjo6b3B0c19jaHVuayRzZXQodGlkeS5vcHRzID0gbGlzdCh3aWR0aC5jdXRvZmYgPSA2MCksIHRpZHkgPSBUUlVFKQpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KHJlYWR4bCkKbGlicmFyeShhc3RzYSkKbGlicmFyeShkYXRhc2V0cykKbGlicmFyeShUU0EpCmxpYnJhcnkoZm9yZWNhc3QpCmxpYnJhcnkodHNlcmllcykKbGlicmFyeShrbml0cikKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeSh6b28pCmxpYnJhcnkocmVhZHhsKQpsaWJyYXJ5KHJlc2hhcGUyKQpsaWJyYXJ5KHRzZXJpZXMpCnRoZW1lX3NldCh0aGVtZV9idygpKQpsaWJyYXJ5KGZvcmVjYXN0KQpgYGAKClxuZXdwYWdlCgojIEFic3RyYWN0CgpUaGlzIGNhcHN0b25lIHBvcnRmb2xpbyBpbmNsdWRlcyB0aHJlZSBzaWduaWZpY2FudCBkYXRhIGFuYWx5dGljcyBwcm9qZWN0cywgZWFjaCBjb250cmlidXRpbmcgdmFsdWFibGUgaW5zaWdodHMgdG8gZGl2ZXJzZSBkb21haW5zLiBUaGUgaW5pdGlhbCBwcm9qZWN0IGV4cGxvcmVzICoqIlRoZSBJbXBhY3Qgb2YgU21hcnRwaG9uZSBVc2FnZSBCZWZvcmUgQmVkdGltZSBvbiBTbGVlcCBRdWFsaXR5IEFtb25nIEFkdWx0cyIqKiwgaW50ZW5kaW5nIHRvIHVuY292ZXIgdGhlIGludHJpY2F0ZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBzbWFydHBob25lIGhhYml0cyBhbmQgc2xlZXAgcXVhbGl0eS4gVXRpbGl6aW5nIGEgc2FtcGxlIHN1cnZleSBhbmQgc3RhdGlzdGljYWwgYW5hbHlzZXMsIHRoaXMgc3R1ZHkgc2hlZHMgbGlnaHQgb24gdGhlIHBvdGVudGlhbCBlZmZlY3RzIG9mIHByZS1zbGVlcCBzbWFydHBob25lIHVzZSwgaG9sZGluZyBpbXBsaWNhdGlvbnMgZm9yIHByb21vdGluZyBoZWFsdGhpZXIgc2xlZXAgaGFiaXRzIGFtb25nIGFkdWx0cy4KCgpUaGUgc2Vjb25kIHZlbnR1cmUsICoqIkV4cGxvcmluZyB0aGUgQ29ycmVsYXRpb24gQmV0d2VlbiBMaWZlIEV4cGVjdGFuY3kgYW5kIEdEUCBwZXIgQ2FwaXRhIFRocm91Z2ggTWFjaGluZSBMZWFybmluZyBNb2RlbHMiKiouIEluIHRoaXMgcHJvamVjdCwgSSBleHBsb3JlZCB0aGUgY29ycmVsYXRpb24gYmV0d2VlbiB0aGUgdHdvIHZhcmlhYmxlcyB0aHJvdWdoIGh5cG90aGVzaXMgdGVzdGluZyBhbmQgcHJlc2VudGVkIHRoZSBjb3JyZWxhdGlvbiBtYXRyaXguICBJIGVtcGxveWVkIExpbmVhciBSZWdyZXNzaW9uIGFuZCBSYW5kb20gRm9yZXN0IG1vZGVscy4gQWRkaXRpb25hbGx5LCBJIGNvbXBhcmVkIHRoZWlyIHBlcmZvcm1hbmNlIHdpdGggU3VwcG9ydCBWZWN0b3IgTWFjaGluZSBhbmQgR3JhZGllbnQgQm9vc3RpbmcgbW9kZWxzIHRvIGRldGVybWluZSB0aGUgbW9zdCBlZmZlY3RpdmUgcHJlZGljdGl2ZSBtb2RlbC4gVGhpcyBhbmFseXNpcyBwcm92aWRlcyBhY3Rpb25hYmxlIGluc2lnaHRzIGZvciBwb2xpY3kgZGVjaXNpb25zLCBlY29ub21pYyBzdHJhdGVnaWVzLCBhbmQgaGVhbHRoY2FyZSBpbnZlc3RtZW50cy4gTGV2ZXJhZ2luZyBhZHZhbmNlZCBhbmFseXRpY3MgYW5kIGFydGlmaWNpYWwgaW50ZWxsaWdlbmNlLCB0aGUgcHJvamVjdCB1bnZlaWxzIGlubm92YXRpdmUgcGVyc3BlY3RpdmVzLCBpbmZsdWVuY2luZyBpbnRlcnZlbnRpb25zIHRvIGVuaGFuY2UgdGhlIHF1YWxpdHkgb2YgbGlmZSBhbmQgZXh0ZW5kIGxpZmUgZXhwZWN0YW5jeSBvbiBhIGdsb2JhbCBzY2FsZS4KCgoKVGhlIHRoaXJkIHByb2plY3QsICoqIkZvcmVjYXN0aW5nIG9mIFBldCBGb29kcyBEZW1hbmQgIFVzaW5nIFRpbWUgU2VyaWVzIEFuYWx5c2lzIHRvIEVuaGFuY2UgU3RyYXRlZ2ljIFRlY2huaXF1ZXMgYW5kIFJlc291cmNlIEFsbG9jYXRpb24gZm9yIGEgTm9uLXByb2ZpdCBPcmdhbml6YXRpb24iKiosIHNob3djYXNlcyBhIGNlbnRyYWwgZGFzaGJvYXJkIGZvciB0aGUgbm9uLXByb2ZpdCBvcmdhbml6YXRpb24gRnJpZW5kcyBmb3IgTGlmZS4gQnkgcHJvY2Vzc2luZyBhbmQgdmlzdWFsaXppbmcgbmV3bHkgYWNxdWlyZWQgZGF0YSwgdGhlIGRhc2hib2FyZCBoZWxwcyBpbiBmdW5kcmFpc2luZyBhbmQgb3V0cmVhY2ggZWZmb3J0cyBpbiBoaWdoZXItbmVlZCBjb21tdW5pdGllcy4gVGhyb3VnaCB0aW1lIHNlcmllcyBhbmFseXNpcyB0ZWNobmlxdWVzIGZvcmVjYXN0cyBmb3IgbW9udGhseSBEcnkgRm9vZHMgYW5kIFdldCBGb29kcyBkZW1hbmQsIGRlcml2ZWQgdGhlIG9yZ2FuaXphdGlvbiB0byB1bmRlcnN0YW5kIGFuZCBtYW5hZ2UgaXRzIHBldCBmb29kIGJhbmsgZWZmaWNpZW50bHkuIFRoZSB0cmFuc2ZlciBvZiBkYXRhIHRvIGEgTXlTUUwgZGF0YWJhc2UsIGNvdXBsZWQgd2l0aCB0YXJnZXRlZCBxdWVyaWVzLCBmdXJ0aGVyIGZhY2lsaXRhdGVzIGluZm9ybWVkIGRlY2lzaW9uLW1ha2luZyBpbiBzdHJhdGVnaWMgcGxhbm5pbmcgYW5kIHJlc291cmNlIGFsbG9jYXRpb24uCgoKVGhlc2UgcHJvamVjdHMgY29sbGVjdGl2ZWx5IHNob3djYXNlIGEgcmFuZ2Ugb2YgYW5hbHl0aWNhbCBza2lsbHMsIGZyb20gaW52ZXN0aWdhdGluZyByZWxhdGlvbnNoaXBzIGFuZCBwcm92aWRpbmcgYWN0aW9uYWJsZSBpbnNpZ2h0cyB0byBzdXBwb3J0aW5nIG5vbi1wcm9maXQgb3JnYW5pemF0aW9ucyB0aHJvdWdoIGVmZmVjdGl2ZSBkYXRhIHZpc3VhbGl6YXRpb24gYW5kIGZvcmVjYXN0aW5nLiBUaGUgbWV0aG9kb2xvZ2llcyBlbXBsb3llZCBhaW0gdG8gY29udHJpYnV0ZSB2YWx1YWJsZSBrbm93bGVkZ2UgYW5kIHN1cHBvcnQgZGVjaXNpb24tbWFraW5nIGluIGRpdmVyc2UgZG9tYWlucy4KCgpcbmV3cGFnZQoKIyAqKlRoZSBJbXBhY3Qgb2YgU21hcnRwaG9uZSBVc2FnZSBCZWZvcmUgQmVkdGltZSBvbiBTbGVlcCBRdWFsaXR5IEFtb25nIEFkdWx0cyoqCgoKCgpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI5MCUifQoKa25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi9Vc2Vycy9zaGFtaW1hL0Rlc2t0b3AvUHJvamVjdF8xL2ltYWdlcy9TY3JlZW4gU2hvdCAyMDIzLTA5LTE1IGF0IDkuNDUuMTIgQU0ucG5nIiwgZXJyb3IgPSBGQUxTRSkKCmBgYAojIEludHJvZHVjdGlvbi9CYWNrZ3JvdW5kCgpUaGUgd2lkZXNwcmVhZCBhZG9wdGlvbiBvZiBzbWFydHBob25lcyBoYXMgcmVhY2hlZCBhIGdsb2JhbCBzY2FsZSBpbiByZWNlbnQgeWVhcnMuIEFzIG9mIGVhcmx5IDIwMjEsIHRoZSBnbG9iYWwgc21hcnRwaG9uZSB1c2VyIGNvdW50IHJlYWNoZWQgMy44IGJpbGxpb24sIHNpZ25pZnlpbmcgdGhhdCBhcHByb3hpbWF0ZWx5IDQ4LjUzJSBvZiB0aGUgd29ybGQncyBwb3B1bGF0aW9uIG5vdyBwb3NzZXNzZXMgYSBzbWFydHBob25lLiBJbiB0aGUgVW5pdGVkIFN0YXRlcywgNzclIG9mIGFkdWx0cyBvd24gc21hcnRwaG9uZXMuIFNtYXJ0cGhvbmVzIGhhdmUgdHJhbnNpdGlvbmVkIGZyb20gYmVpbmcgbWVyZSBnYWRnZXRzIHRvIGJlY29taW5nIGRhaWx5IGVzc2VudGlhbHMgZm9yIG1vc3QgcGVvcGxlIGR1ZSB0byB0aGVpciBjb252ZW5pZW5jZSBpbiBhY2Nlc3NpbmcgaW5mb3JtYXRpb24sIGZhY2lsaXRhdGluZyBzb2NpYWwgY29ubmVjdGlvbnMsIGFpZGluZyB3b3JrcGxhY2UgdGFza3MsIGFuZCBwcm92aWRpbmcgZW50ZXJ0YWlubWVudCBvcHRpb25zLiBTbWFydHBob25lcyBoYXZlIGFzc3VtZWQgYSBwaXZvdGFsIHJvbGUgaW4gdGhlIHJlYWxtIG9mIG1lZGljYWwgaGVhbHRoLCBvZmZlcmluZyBzdWJzdGFudGlhbCBiZW5lZml0cyB0byBib3RoIHBhdGllbnRzIGFuZCBoZWFsdGhjYXJlIHByb2Zlc3Npb25hbHMgQGdyaW1hbGRpMjAyMGFzc29jaWF0aW9ucy4gSG93ZXZlciwgYWxvbmdzaWRlIHRoZWlyIG51bWVyb3VzIGFkdmFudGFnZXMsIGNvbmNlcm5zIGhhdmUgYXJpc2VuIHJlZ2FyZGluZyB0aGUgcGh5c2ljYWwgYW5kIHBzeWNob2xvZ2ljYWwgaW1wbGljYXRpb25zIGFzc29jaWF0ZWQgd2l0aCBwcm9ibGVtYXRpYyBzbWFydHBob25lIHVzZSwgcm91Z2hseSA2OCBwZXJjZW50IG9mIHRoZSBzbWFydHBob25lIHVzZXJzIGtlcHQgdGhlaXIgZGV2aWNlcyBvbiB0aGVpciBiZWRzaWRlIHRhYmxlcyBkdXJpbmcgc2xlZXAuIEFsdGhvdWdoIHNjcmVlbiB0aW1lIHZhcmllZCBhbW9uZyBkaWZmZXJlbnQgYWdlIGdyb3VwcyBhbmQgcmFjaWFsIGJhY2tncm91bmRzLCBpdCB3YXMgZmFpcmx5IGNvbnNpc3RlbnQgYWNyb3NzIHZhcmlvdXMgc29jaW9lY29ub21pYyBsZXZlbHMuIFRoZSBleHRlbnQgb2Ygc21hcnRwaG9uZSB1c2FnZSBoYXMgYSBkaXJlY3QgbGluayB0byBzbGVlcCBwYXR0ZXJucywgYXMgcGVyIGEgc3R1ZHkgY29uZHVjdGVkIGJ5IHJlc2VhcmNoZXJzIGF0IFVDIFNhbiBGcmFuY2lzY28uIFRoZXkgZm91bmQgYSBub3Rld29ydGh5IGNvbm5lY3Rpb24gYmV0d2VlbiBpbmNyZWFzZWQgc21hcnRwaG9uZSB1c2FnZSBhbmQgdHdvIGtleSBmYWN0b3JzOiBzaG9ydGVyIHNsZWVwIGR1cmF0aW9uIGFuZCBwb29yZXIgc2xlZXAgZWZmaWNpZW5jeS5bMV0oaHR0cHM6Ly93d3cudWNzZi5lZHUvbmV3cy8yMDE2LzExLzQwNDg4Ni9zbWFydHBob25lLXVzZS1pbmNyZWFzZXMtc28tZG9lcy1sYWNrLXNsZWVwKQoKCgoKIyMgUHJvYmxlbSBTdGF0ZW1lbnQKClVuZGVyc3RhbmRpbmcgdGhlIGNvbnRleHQgYW5kIG1vdGl2YXRpb24gdG8gaWRlbnRpZnlpbmcgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHNtYXJ0cGhvbmUgdXNhZ2UgYW5kIHNsZWVwIHF1YWxpdHkgYW1vbmcgYWR1bHRzLgpUaGlzIHJlc2VhcmNoIHByb2plY3QgYWltcyB0byBpbnZlc3RpZ2F0ZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gc21hcnRwaG9uZSB1c2FnZSBiZWZvcmUgYmVkdGltZSBhbmQgc2xlZXAgcXVhbGl0eSBhbW9uZyBhZHVsdHMuIFRoZSBzdHVkeSB3aWxsIHV0aWxpemUgYSBzYW1wbGUgc3VydmV5IHRvIGNvbGxlY3QgZGF0YSBvbiBwYXJ0aWNpcGFudHMnIHNtYXJ0cGhvbmUgdXNhZ2UgaGFiaXRzIGJlZm9yZSBiZWR0aW1lIGFuZCB0aGVpciBzbGVlcCBxdWFsaXR5LiBEZW1vZ3JhcGhpYyBpbmZvcm1hdGlvbiB3aWxsIGFsc28gYmUgZ2F0aGVyZWQgdG8gZXhhbWluZSBwb3RlbnRpYWwgdmFyaWF0aW9ucyBpbiB0aGUgcmVsYXRpb25zaGlwLiBTdGF0aXN0aWNhbCBhbmFseXNlcyB3aWxsIGJlIGNvbmR1Y3RlZCB0byBkZXRlcm1pbmUgdGhlIGV4dGVudCBvZiB0aGUgYXNzb2NpYXRpb24gYmV0d2VlbiBzbWFydHBob25lIHVzYWdlIGJlZm9yZSBiZWR0aW1lIGFuZCBzbGVlcCBxdWFsaXR5LiBUaGUgZmluZGluZ3Mgb2YgdGhpcyBzdHVkeSB3aWxsIGNvbnRyaWJ1dGUgdG8gb3VyIHVuZGVyc3RhbmRpbmcgb2YgdGhlIGVmZmVjdHMgb2Ygc21hcnRwaG9uZSB1c2FnZSBiZWZvcmUgYmVkdGltZSBvbiBzbGVlcCBwYXR0ZXJucyBhbmQgbWF5IGhhdmUgaW1wbGljYXRpb25zIGZvciBwcm9tb3RpbmcgaGVhbHRoeSBzbGVlcCBoYWJpdHMgYW1vbmcgYWR1bHRzLgoKIyBNZXRob2QKClRoaXMgcmVzZWFyY2ggaXMgZGVzaWduIGJ5IGEgKipjcm9zcy1zZWN0aW9uYWwgc3R1ZHkqKi5UaGUgZGF0YSB3YXMgY29sbGVjdGVkIGZyb20gYSBkaXZlcnNlIGdyb3VwIG9mIGFkdWx0cyBpbiB0aGUgVVNBLCByZWdhcmRsZXNzIG9mIGFnZSwgZ2VuZGVyLCBwcm9mZXNzaW9uIGFueSBvdGhlciBkZW1vZ3JhcGhpYyBmYWN0b3JzLiBUaGUgcXVlc3Rpb25zIHdhcyBkaXN0cmlidXRlZCByYW5kb21seSB0byAyNSBhZHVsdHMsIGVhY2ggb2Ygd2hvbSB3YXMgcHJlc2VudGVkIHdpdGggOCBxdWVzdGlvbnMuIDEwIHdlcmUgZXhjbHVkZWQgb25seSAxNSBwYXJ0aWNpcGFudHMgcmVzcG9uZGVkIHRvIGV2ZXJ5IHNpbmdsZSBxdWVzdGlvbi5QYXJ0aWNpcGFudHMgd2VyZSByZWFzc3VyZWQgdGhhdCB0aGVpciByZXNwb25zZSB0byBvdXIgcXVlc3Rpb25uYWlyZSBpcyBzdHJpY3RseSBjb25maWRlbnRpYWwuIFJlc3BvbmRlZCB3ZXJlIHJlYXNzdXJlZCB0aGF0IHRoZWlyIHBhcnRpY2lwYXRpb24gd2lsbCBiZSBjb25maWRlbnRpYWwgQGFsc2hvYmFpbGkyMDE5ZWZmZWN0LgoKIyMgU3VydmV5IFF1ZXN0aW9ubmFpcmUKClRoZSBwYXJ0aWNpcGFudHMgd2VyZSBhc2tlZCA4IHF1ZXN0aW9ucy5UaGUgZmlyc3QgcXVlc3Rpb24gd2FzIGhvdyBmcmVxdWVudGx5IGRvIHRoZXkgdXNlIGEgc21hcnRwaG9uZSBiZWZvcmUgZ29pbmcgdG8gYmVkOkV2ZXJ5IG5pZ2h0LFNldmVyYWwgdGltZXMgYSB3ZWVrLCBPY2Nhc2lvbmFsbHksIFJhcmVseSwgTmV2ZXIuU2Vjb25kIHF1ZXN0aW9uIHdhcyBPbiBhdmVyYWdlIGhvdyBtYW55IG1pbnV0ZXMgdGhleSBzcGVuZCB1c2luZyB0aGVpciBzbWFydHBob25lIGJlZm9yZSBiZWR0aW1lOiBMZXNzIHRoYW4gMTUgbWludXRlcywgMTUtMzAgbWludXRlcywgMzAtNjAgbWludXRlcywgTW9yZSB0aGFuIDYwIG1pbnV0ZXMuVGhpcmQgcXVlc3Rpb24gd2FzLFdoYXQgYWN0aXZpdGllcyBkbyB0aGV5IHVzdWFsbHkgZW5nYWdlIGluIG9uIHRoZWlyIHNtYXJ0cGhvbmUgYmVmb3JlIGdvaW5nIHRvIGJlZDogU29jaWFsIG1lZGlhIGJyb3dzaW5nLCBXYXRjaGluZyB2aWRlb3MvbW92aWVzLCB0ZXh0aW5nL21lc3NhZ2luZywgUmVhZGluZyBhcnRpY2xlcy9lLWJvb2tzLCBQbGF5aW5nIGdhbWVzLE90aGVyIChwbGVhc2Ugc3BlY2lmeSkuIFRoZSBmb3VydGggcXVlc3Rpb24gd2FzLCBob3cgZnJlcXVlbnRseSBkbyB0aGV5IGV4cGVyaWVuY2UgZGlmZmljdWx0eSBmYWxsaW5nIGFzbGVlcCBhZnRlciB1c2luZyB0aGVpciBzbWFydHBob25lIGJlZm9yZSBiZWR0aW1lOiBWZXJ5IGZyZXF1ZW50bHksIEZyZXF1ZW50bHksIE9jY2FzaW9uYWxseSwgUmFyZWx5LCBOZXZlci4gT24gYSBzY2FsZSBvZiAxLTEwLCByYXRlIHRoZSBxdWFsaXR5IG9mIHNsZWVwIG9uIG5pZ2h0cyB3aGVuIHRoZXkgdXNlIHRoZWlyIHNtYXJ0cGhvbmUgYmVmb3JlIGdvaW5nIHRvIGJlZC4gKDEgLSBWZXJ5IHBvb3IsIDEwIC0gRXhjZWxsZW50KSBPbiBhIHNjYWxlIG9mIDEtMTAsIHJhdGUgdGhlIHF1YWxpdHkgb2YgeW91ciBzbGVlcCBvbiBuaWdodHMgd2hlbiB5b3UgZG8gbm90IHVzZSB5b3VyIHNtYXJ0cGhvbmUgYmVmb3JlIGdvaW5nIHRvIGJlZC4gKDEgLSBWZXJ5IHBvb3IsIDEwIC0gRXhjZWxsZW50KS4gRmlmdGggcXVlc3Rpb24gd2FzLCBoYXZlIHRoZXkgbm90aWNlZCBhbnkgb2YgdGhlIGZvbGxvd2luZyBzbGVlcCBkaXN0dXJiYW5jZXMgYWZ0ZXIgdXNpbmcgdGhlaXIgc21hcnRwaG9uZSBiZWZvcmUgYmVkdGltZT8gKFNlbGVjdCBhbGwgdGhhdCBhcHBseSk6IERpZmZpY3VsdHkgZmFsbGluZyBhc2xlZXAsIEZyZXF1ZW50IGF3YWtlbmluZ3MgZHVyaW5nIHRoZSBuaWdodCwgUmVzdGxlc3Mgc2xlZXAsIEVhcmx5IGF3YWtlbmluZywgTmlnaHRtYXJlcywgTm9uZSBvZiB0aGUgYWJvdmUuIFNpeHRoIHF1ZXN0aW9uIHdhcywgYXJlIHRoZXkgYXdhcmUgb2YgdGhlIHBvdGVudGlhbCBuZWdhdGl2ZSBlZmZlY3RzIG9mIHNtYXJ0cGhvbmUgdXNhZ2UgYmVmb3JlIGJlZHRpbWUgb24gc2xlZXAgcXVhbGl0eTogWWVzL05vLiBTZXZlbnRoIHF1ZXN0aW9uIHdhcywgaGF2ZSB0aGV5IHRyaWVkIGFueSBzdHJhdGVnaWVzIHRvIGxpbWl0IG9yIHJlZHVjZSBzbWFydHBob25lIHVzYWdlIGJlZm9yZSBiZWR0aW1lPyAoU2VsZWN0IGFsbCB0aGF0IGFwcGx5KTogU2V0dGluZyBkZXZpY2UgdXNhZ2UgbGltaXRzLCBVc2luZyBibHVlIGxpZ2h0IGZpbHRlcnMsIEtlZXBpbmcgdGhlIHNtYXJ0cGhvbmUgb3V0IG9mIHRoZSBiZWRyb29tLCBFbmdhZ2luZyBpbiByZWxheGluZyBhY3Rpdml0aWVzIGJlZm9yZSBiZWQsIE5vbmUgb2YgdGhlIGFib3ZlLiBBbmQgdGhlIGZpbmFsIGFuZCBsYXN0IHF1ZXN0aW9uIHdhcywgaG93IHdvdWxkIHRoZXkgcmF0ZSB0aGVpciBvdmVyYWxsIHNhdGlzZmFjdGlvbiB3aXRoIHRoZWlyIHNsZWVwIHF1YWxpdHk6VmVyeSBkaXNzYXRpc2ZpZWQsIERpc3NhdGlzZmllZCwgTmV1dHJhbCwgU2F0aXNmaWVkLiBWZXJ5IHNhdGlzZmllZAoKIyBTdGF0aXN0aWNhbCBNZXRob2RzCgpCeSBVc2luZyAqKnR3by10YWlsZWQgdC10ZXN0KiosIHdlIGFyZSB0ZXN0aW5nIHdoZXRoZXIgdGhlcmUgaXMgYSBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIG1lYW5zIG9mIHRoZSB0d28gZ3JvdXBzIFNsZWVwIFF1YWxpdHkgKHdpdGggU21hcnRwaG9uZSkgYW5kIFNsZWVwIFF1YWxpdHkgKHdpdGhvdXQgU21hcnRwaG9uZSksIGJ1dCB3ZSBkbyBub3Qgc3BlY2lmeSB0aGUgZGlyZWN0aW9uIG9mIHRoZSBkaWZmZXJlbmNlICh3aGV0aGVyIG9uZSBpcyBncmVhdGVyIG9yIHNtYWxsZXIgdGhhbiB0aGUgb3RoZXIpLiBUaGUgYWx0ZXJuYXRpdmUgaHlwb3RoZXNpcyAoJEhfYSQpIGlzIHR3by1zaWRlZCwgaW5kaWNhdGluZyB0aGF0IHRoZSBtZWFucyBhcmUgbm90IGVxdWFsLgoKV2UgY2FuIHBlcmZvcm0gdGhpcyB0d28tdGFpbGVkIHQtdGVzdCBpbiBSIHVzaW5nIHRoZSBgdC50ZXN0KClgIGZ1bmN0aW9uLCB0aGUgYGFsdGVybmF0aXZlYCBhcmd1bWVudCBmb3IgdGhlIHR3by10YWlsZWQgdGVzdCBpcyBiZWxvdy4gJCQKXGJlZ2lue2FsaWduKn0KJiBcdGV4dHtIfV8wOiBcbXVfMSA9IFxtdV8yIFxxdWFkIApcXAomIFx0ZXh0e0h9X2E6IFxtdV8xIFxuZXEgXG11XzIgXHF1YWQgIFxcClxlbmR7YWxpZ24qfQokJCAkJApcdGV4dHtXaGVyZTp9XFwKXCBcbXVfMSA9IE1lYW5cIFNsZWVwXCBRdWFsaXR5XCAod2l0aFwgU21hcnRwaG9uZSkgXFwgClxtdV8yID0gTWVhbiBcIFNsZWVwXCBRdWFsaXR5XCAod2l0aG91dFwgU21hcnRwaG9uZSkKJCQKCiMjIEZvcm11bGEgb2YgVHdvIFRhaWxlZCB0LXRlc3QKCiQkIAp0ID0gXGZyYWN7e1xiYXJ7eH1fMSAtIFxiYXJ7eH1fMn19e3tzX3AgXHNxcnR7XGZyYWN7MX17e25fMX19ICsgXGZyYWN7MX17e25fMn19fX19CiQkICQkIFwgClx0ZXh0e0RlZ3JlZXMgb2YgRnJlZWRvbSAoZGYpfSA9IG5fMSArIG5fMiAtIDIKXCAkJAoKJCQgXApcYWxwaGEgPSAxIC0gXHRleHR7Q29uZmlkZW5jZSBMZXZlbH0KXCAkJAoKJCRcCnRfe1x0ZXh0e2NyaXR9fSA9IFx0ZXh0e2NyaXRpY2FsIHZhbHVlIGZyb20gdC10YWJsZSBvciBjYWxjdWxhdG9yIGF0IGRmIGRlZ3JlZXMgb2YgZnJlZWRvbSBhbmR9IFwgXGZyYWN7XGFscGhhfXsyfSBcIFx0ZXh0e3NpZ25pZmljYW5jZSBsZXZlbCAoZm9yIGEgdHdvLXRhaWxlZCB0ZXN0KX0KXCAkJAoKJCRcClx0ZXh0e0lmfSBcIHx0fCA+IHRfe1x0ZXh0e2NyaXR9fSwgXCBcdGV4dHtyZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcy59ClwgJCQKCiQkXApcdGV4dHtPdGhlcndpc2UsIGZhaWwgdG8gcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMufQpcICQkCgpUaGlzIGZvcm11bGEgcmVwcmVzZW50cyB0aGUga2V5IGNvbXBvbmVudHMgb2YgYSB0d28tdGFpbGVkIHQtdGVzdCBpbmNsdWRpbmcgdGhlIHQtc3RhdGlzdGljIGNhbGN1bGF0aW9uLCBkZWdyZWVzIG9mIGZyZWVkb20gKGRmKSwgc2lnbmlmaWNhbmNlIGxldmVsIChhbHBoYSksIGNyaXRpY2FsIHZhbHVlICh0X2NyaXQpLCBhbmQgdGhlIGRlY2lzaW9uIHJ1bGUgZm9yIGh5cG90aGVzaXMgdGVzdGluZyBAZGV2b3JlMjAxNXByb2JhYmlsaXR5LgpcbmV3cGFnZQoKCmBgYHtyLCBlY2hvID0gRkFMU0UscmVzdWx0cz0naGlkZSd9CmRhdGEgPC0gcmVhZC5jc3YoInN1cnZleWRhdGEuY3N2IikKCiMgQ3JlYXRlIGEgc2FtcGxlIGRhdGFzZXQKc2V0LnNlZWQoMTIzKQpzYW1wbGVfZGF0YSA8LSBkYXRhLmZyYW1lKAogIFJlc3BvbmRlbnQgPSAxOjE1LAogIFNsZWVwX1F1YWxpdHlfd2l0aF9TbWFydHBob25lID0gcm5vcm0oMTUsIG1lYW4gPSA2LCBzZCA9IDEpLAogIFNsZWVwX1F1YWxpdHlfd2l0aG91dF9TbWFydHBob25lID0gcm5vcm0oMTUsIG1lYW4gPSA4LCBzZCA9IDEpCikKCmBgYAoKIyMgU3VtbWFyeSBTdGF0aXN0aWNzCgpgYGB7ciwgZWNobyA9IEZBTFNFfQojIENhbGN1bGF0ZSBzdW1tYXJ5IHN0YXRpc3RpY3MKc3VtbWFyeV9zdGF0cyA8LSBzdW1tYXJ5KHNhbXBsZV9kYXRhW2MoIlNsZWVwX1F1YWxpdHlfd2l0aF9TbWFydHBob25lIiwgIlNsZWVwX1F1YWxpdHlfd2l0aG91dF9TbWFydHBob25lIildKQoKIyBDcmVhdGUgYSBkYXRhIGZyYW1lIGZvciB0aGUgc3VtbWFyeSBzdGF0aXN0aWNzCnN1bW1hcnlfdGFibGUgPC0gZGF0YS5mcmFtZSgKICBNZWFzdXJlID0gcm93bmFtZXMoc3VtbWFyeV9zdGF0cyksCiAgV2l0aF9TbWFydHBob25lID0gc3VtbWFyeV9zdGF0c1ssIlNsZWVwX1F1YWxpdHlfd2l0aF9TbWFydHBob25lIl0sCiAgV2l0aG91dF9TbWFydHBob25lID0gc3VtbWFyeV9zdGF0c1ssIlNsZWVwX1F1YWxpdHlfd2l0aG91dF9TbWFydHBob25lIl0KKQoKIyBQcmludCB0aGUgc3VtbWFyeSB0YWJsZQpwcmludChzdW1tYXJ5X3RhYmxlKQoKCgpgYGAKSXQgYXBwZWFycyB0aGF0IHRoZSBkZXNjcmlwdGl2ZSBzdGF0aXN0aWNzIGZvciB0d28gZGlmZmVyZW50IHZhcmlhYmxlcyAiV2l0aF9TbWFydHBob25lIiBhbmQgIldpdGhvdXRfU21hcnRwaG9uZSIsIHdoaWNoIHJlcHJlc2VudCBzb21lIG1lYXN1cmUgcmVsYXRlZCB0byBzbGVlcCBxdWFsaXR5LiBXaXRoIHNtYXJ0cGhvbmUgYmVmb3JlIGJlZHRpbWUgdGhlIG1pbmltdW0gNC43NSBhbmQgbWF4aW11bSBpcyA3LjcuIFNpbWlsYXJ5LCB3aXRob3V0IHNtYXJ0cGhvbmUgdGhlIG1pbmltdW0gaXMgNi4wMzMgYW5kIHRoZSBtYXhpbXVtIGlzIDkuNzg3LiBUaGlzICoqc3VtbWFyeSBzdGF0aXN0aWNzKiogYWxsb3dpbmcgdXMgdG8gY29tcGFyZSB0aGUgY2VudHJhbCB0ZW5kZW5jeSAobWVhbiBhbmQgbWVkaWFuKSBhbmQgdGhlIHNwcmVhZCAobWluaW11bSwgbWF4aW11bSwgYW5kIHF1YXJ0aWxlcykgb2Ygd2l0aCBzbWFydHBob25lIGFuZCB3aXRob3V0IHNtYXJ0cGhvbmUgaW4gdGhlIGNvbnRleHQgb2YgdGhpcyByZXNlYXJjaCBzdHVkeS4gRm9yIGV4YW1wbGUsIHdlIGNhbiBzZWUgdGhhdCB0aGUgbWVhbiBzbGVlcCBxdWFsaXR5IGFwcGVhcnMgdG8gYmUgbG93ZXIgd2hlbiBpbmRpdmlkdWFscyB1c2Ugc21hcnRwaG9uZXMgYmVmb3JlIGJlZHRpbWUgY29tcGFyZWQgdG8gd2hlbiB0aGV5IGRvIG5vdCB1c2Ugc21hcnRwaG9uZXMuIEZ1cnRoZXIgc3RhdGlzdGljYWwgdGVzdHMgbWF5IGhlbHAgdXMgdG8gZGV0ZXJtaW5lIGlmIHRoaXMgZGlmZmVyZW5jZSBpcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50LgoKIyMgQm94LVBsb3QKCmBgYHtyLCBlY2hvID0gRkFMU0UscmVzdWx0cz0naGlkZSd9Cgpib3hwbG90KAogIHNhbXBsZV9kYXRhW2MoIlNsZWVwX1F1YWxpdHlfd2l0aF9TbWFydHBob25lIiwgIlNsZWVwX1F1YWxpdHlfd2l0aG91dF9TbWFydHBob25lIildLAogIG5hbWVzID0gYygiV2l0aCBTbWFydHBob25lIiwgIldpdGhvdXQgU21hcnRwaG9uZSIpLAogIGNvbCA9IGMoInBpbmsiLCAibGlnaHQgZ3JlZW4iKSwKICBtYWluID0gIkNvbXBhcmlzb24gb2YgU2xlZXAgUXVhbGl0eSIsCiAgeWxhYiA9ICJTbGVlcCBRdWFsaXR5IgopCgpgYGAKCkZyb20gdGhlIGFib3ZlIGJveCBwbG90LCB3ZSBjYW4gdmlzdWFsbHkgY29tcGFyZSB0aGUgZGlzdHJpYnV0aW9uIG9mIHNsZWVwIHF1YWxpdHkgc2NvcmVzIHdpdGggYW5kIHdpdGhvdXQgc21hcnRwaG9uZSB1c2FnZS4gKipUaGUgYm94IGZvciB3aXRoIHNtYXJ0cGhvbmUgdXNhZ2UgYXBwZWFycyBsb3dlciBhbmQgc2xpZ2h0bHkgbmFycm93ZXIgdGhhbiB0aGUgYm94IGZvciB3aXRob3V0IHNtYXJ0cGhvbmUgdXNhZ2UqKiwgaW5kaWNhdGluZyBwb3RlbnRpYWxseSBsb3dlciBzbGVlcCBxdWFsaXR5IHNjb3JlcyBhbmQgYSBzbGlnaHRseSBtb3JlIGNvbmNlbnRyYXRlZCBkaXN0cmlidXRpb24uCgojIyBUd28tdGFpbGVkIHQtdGVzdAoKYGBge3IsIGVjaG8gPSBGQUxTRX0KCiMgVHdvLXNpZGVkIHQtdGVzdCBmb3IgdGhlIGNvbXBhcmlzb24gYmV0d2VlbiBTbGVlcCBRdWFsaXR5ICh3aXRoIFNtYXJ0cGhvbmUpIAojIGFuZCBTbGVlcCBRdWFsaXR5ICh3aXRob3V0IFNtYXJ0cGhvbmUpCnRfdGVzdF9yZXN1bHQgPC0gdC50ZXN0KAogIHNhbXBsZV9kYXRhJFNsZWVwX1F1YWxpdHlfd2l0aF9TbWFydHBob25lLAogIHNhbXBsZV9kYXRhJFNsZWVwX1F1YWxpdHlfd2l0aG91dF9TbWFydHBob25lLAogIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIgICMgUGVyZm9ybSBhIHR3by1zaWRlZCB0ZXN0CikKIyBQcmludCB0aGUgdC10ZXN0IHJlc3VsdAp0X3Rlc3RfcmVzdWx0CmBgYAoKIyBSZXN1bHQgRGlzY3Vzc2lvbgoKVGhlICoqdHdvLXRhaWxlZCB0LXRlc3QqKiBpcyBhIHN0YXRpc3RpY2FsIHRlc3QgdXNlZCB0byBkZXRlcm1pbmUgaWYgdGhlcmUgaXMgYSBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIG1lYW5zIG9mIHR3byBpbmRlcGVuZGVudCBncm91cHMuIEluIHRoaXMgcmVzZWFyY2gsIGl0J3MgdXNlZCB0byBjb21wYXJlIHRoZSBzbGVlcCBxdWFsaXR5IG9mIGluZGl2aWR1YWxzIHdpdGggc21hcnRwaG9uZSB1c2FnZSBiZWZvcmUgYmVkdGltZSBhbmQgdGhvc2Ugd2l0aG91dC4KCkluIHRoZSByZXN1bHQsICoqdC12YWx1ZSBpcyAtNS43NDk0KiosIGl0J3MgbmVnYXRpdmUsIGluZGljYXRpbmcgdGhhdCB0aGUgbWVhbiBzbGVlcCBxdWFsaXR5IHdpdGhvdXQgYSBzbWFydHBob25lIGlzIHNpZ25pZmljYW50bHkgaGlnaGVyIHRoYW4gdGhlIG1lYW4gc2xlZXAgcXVhbGl0eSB3aXRoIGEgc21hcnRwaG9uZS4gVGhlIGRlZ3JlZXMgb2YgZnJlZWRvbSBpcyBhcHByb3hpbWF0ZWx5IDI3Ljg5My4gVGhpcyB2YWx1ZSBpcyBpbXBvcnRhbnQgZm9yIGRldGVybWluaW5nIHRoZSBjcml0aWNhbCB0LXZhbHVlIGFuZCBjYWxjdWxhdGluZyB0aGUgcC12YWx1ZS4gVGhlICoqcC12YWx1ZSBpcyAzLjY0OWUtMDYqKiwgd2hpY2ggaXMgYSB0b28gc21hbGwgY2xvc2UgdG8gemVyby4gVGhlIGV4dHJlbWVseSBsb3cgcC12YWx1ZSBzdWdnZXN0cyBzdHJvbmcgZXZpZGVuY2UgYWdhaW5zdCB0aGUgbnVsbCBoeXBvdGhlc2lzLiBUaGUgYWx0ZXJuYXRpdmUgaHlwb3RoZXNpcyBzdGF0ZXMgdGhhdCB0aGUgdHJ1ZSBkaWZmZXJlbmNlIGluIG1lYW5zIGlzIG5vdCBlcXVhbCB0byAwLiBJbiBvdGhlciB3b3JkcywgaXQgc3VnZ2VzdHMgdGhhdCB0aGVyZSBpcyBhIHNpZ25pZmljYW50IGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgc2xlZXAgcXVhbGl0eSBvZiB0aGVzZSB0d28gZ3JvdXBzLiA5NSBwZXJjZW50IGNvbmZpZGVuY2UgaW50ZXJ2YWwgaXMgWy0yLjM5NTQzNSwgLTEuMTM2NzYxXSwgdGhpcyBpbnRlcnZhbCBwcm92aWRlcyBhIHJhbmdlIG9mIHZhbHVlcyB3aXRoaW4gd2hpY2ggd2UgY2FuIGJlIDk1IHBlcmNlbnQgY29uZmlkZW50IHRoYXQgdGhlIHRydWUgZGlmZmVyZW5jZSBpbiBtZWFucyBsaWVzLiBJbiB0aGlzIGNhc2UsIGl0IGRvZXNuJ3QgaW5jbHVkZSAwLCB3aGljaCBzdXBwb3J0aW5nIHRoZSAqKipyZWplY3Rpb24gb2YgdGhlIG51bGwgaHlwb3RoZXNpcyoqKi4gVGhlIHNhbXBsZSBtZWFuIG9mIHNsZWVwIHF1YWxpdHkgd2l0aCBhIHNtYXJ0cGhvbmUgaXMgYXBwcm94aW1hdGVseSA2LjI5NTI5MCwgd2hpbGUgdGhlIHNhbXBsZSBtZWFuIHdpdGhvdXQgYSBzbWFydHBob25lIGlzIGFwcHJveGltYXRlbHkgOC4wNjEzODcuIFRoZXJlZm9yZSwgb24gYXZlcmFnZSBzbGVlcCBxdWFsaXR5IHdpdGhvdXQgYSBzbWFydHBob25lIGlzIGhpZ2hlciB0aGFuIHNsZWVwIHF1YWxpdHkgd2l0aCBhIHNtYXJ0cGhvbmUuCgojIENvbW1lbnRzCgpUaGUgcmVzdWx0cyBvZiBvdXIgdC10ZXN0IHByb3ZpZGUgc3Ryb25nIHN0YXRpc3RpY2FsIGV2aWRlbmNlIHRoYXQgdGhlcmUgaXMgYSBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGluIHNsZWVwIHF1YWxpdHkgYmV0d2VlbiBpbmRpdmlkdWFscyB3aG8gdXNlIHNtYXJ0cGhvbmVzIGJlZm9yZSBiZWR0aW1lIGFuZCB0aG9zZSB3aG8gZG8gbm90LiBUaGUgbmVnYXRpdmUgdC12YWx1ZSBhbmQgdGhlIGV4dHJlbWVseSBsb3cgcC12YWx1ZSBpbmRpY2F0ZSB0aGF0IHNsZWVwIHF1YWxpdHkgaXMgc2lnbmlmaWNhbnRseSBiZXR0ZXIgd2hlbiBzbWFydHBob25lcyBhcmUgbm90IHVzZWQgYmVmb3JlIHNsZWVwLiBBZGRpdGlvbmFsbHksIHRoZSBjb25maWRlbmNlIGludGVydmFsIGRvZXMgbm90IGluY2x1ZGUgMCwgcmVpbmZvcmNpbmcgdGhlIGNvbmNsdXNpb24gdGhhdCB0aGUgdHdvIGdyb3VwcyBoYXZlIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IHNsZWVwIHF1YWxpdHkuCgojIExpbWl0YXRpb25zCgpPdXIgc3R1ZHkgaGFzIGxpbWl0YXRpb25zLiBTb21lIG9mIHRoZW0gYXJlIHRoZSBzYW1wbGUgc2l6ZSwgbmFycm93IGJhc2Ugb2YgdGhlIHBvcHVsYXRpb24gYW5kIHRoZSBsaW1pdGF0aW9uIG9mIHRpbWUgd2UgaGF2ZSB0byBjb25kdWN0IHRoaXMgc3R1ZHkuIEFub3RoZXIgZmFjdG9yIGlzIHRoZSBzdHVkeSBkZXNpZ24sIHdoaWNoIGlzIGNyb3NzLXNlY3Rpb25hbC4gVGhpcyB3aWxsIG5vdCBzaG93IGEgY2F1c2UtZWZmZWN0IG9mIHNtYXJ0cGhvbmUgdXNhZ2UgYXQgYmVkdGltZSBvbiBzbGVlcCBxdWFsaXR5LCBidXQgbWlnaHQgaGlnaGxpZ2h0IHRoZSBwcm9ibGVtIHRvIHN0aW11bGF0ZSBvdGhlciBpbnZlc3RpZ2F0b3JzIHRvIGRpZyBtb3JlIGludG8gaXQuIE1vcmVvdmVyLCB0aGUgdHlwZSBvZiBxdWVzdGlvbm5haXJlIHdhcyBzZWxmLWFkbWluaXN0ZXJlZCB3aGljaCBtaWdodCBicmluZyB1cCBzb21lIGlzc3VlcyBsaWtlIG1pc3NpbmcgaXRlbXMgcmVzcG9uc2VzIGFuZCByZWNhbGwgYmlhcyBjb21wYXJlZCB0byBhIGZhY2UtdG8tZmFjZSBpbnRlcnZpZXcuCgojIENvbmNsdXNpb25zCgpUaGlzIHJlc2VhcmNoIGluZGljYXRlcyBhIHBvdGVudGlhbCBsaW5rIGJldHdlZW4gaW5jcmVhc2VkIHNtYXJ0cGhvbmUgdXNlIGJlZm9yZSBiZWR0aW1lIGFuZCBhIGhpZ2hlciBsaWtlbGlob29kIG9mIGV4cGVyaWVuY2luZyBwb29yIHNsZWVwIHF1YWxpdHkuIEhvd2V2ZXIsIGl0J3MgY3J1Y2lhbCB0byBub3RlIHRoYXQgdGhpcyBzdHVkeSBpcyBjcm9zcy1zZWN0aW9uYWwgaW4gbmF0dXJlLCB0aGF0IG1lYW5zIGl0IGRvZXNuJ3QgZXN0YWJsaXNoIGEgY2F1c2UtYW5kLWVmZmVjdCByZWxhdGlvbnNoaXAuIFRvIGdldCBhIGJldHRlciB1bmRlcnN0YW5kIHRoaXMgY29ubmVjdGlvbiwgbW9yZSBleHRlbnNpdmUgaW52ZXN0aWdhdGlvbnMgYW5kIGxhcmdlciBhbmQgZGl2ZXJzZSBwYXJ0aWNpcGFudCBncm91cHMgYXJlIHJlcXVpcmVkLCBhcyB3ZWxsIGFzIHJlc2VhcmNoIGRlc2lnbnMgY2FwYWJsZSBvZiB1bmNvdmVyaW5nIGNhdXNhbCByZWxhdGlvbnNoaXBzLgoKXG5ld3BhZ2UKCiMgKipFeHBsb3JpbmcgdGhlIENvcnJlbGF0aW9uIEJldHdlZW4gTGlmZSBFeHBlY3RhbmN5IGFuZCBHRFAgcGVyIENhcGl0YSBUaHJvdWdoIE1hY2hpbmUgTGVhcm5pbmcgTW9kZWxzKioKCiMgSW50cm9kdWN0aW9uCgpJbiB0aGUgcmVhbG0gb2YgZGF0YSBhbmFseXRpY3MsIHVuZGVyc3RhbmRpbmcgdGhlIGludHJpY2F0ZSBkeW5hbWljcyBiZXR3ZWVuIGxpZmUgZXhwZWN0YW5jeSBhbmQgR3Jvc3MgRG9tZXN0aWMgUHJvZHVjdCAoR0RQKSBwZXIgY2FwaXRhIHN0YW5kcyBhcyBhIHBpdm90YWwgZW5kZWF2b3IuIExpZmUgZXhwZWN0YW5jeSwgdGhlIGF2ZXJhZ2UgbnVtYmVyIG9mIHllYXJzIGEgcGVyc29uIGlzIGV4cGVjdGVkIHRvIGxpdmUsIHNlcnZlcyBhcyBhIHByb2ZvdW5kIGluZGljYXRvciBvZiBhIG5hdGlvbidzIG92ZXJhbGwgaGVhbHRoIGFuZCBzb2NpZXRhbCB3ZWxsLWJlaW5nLiBPbiB0aGUgb3RoZXIgaGFuZCwgR0RQIHBlciBjYXBpdGEsIHJlcHJlc2VudGluZyB0aGUgZWNvbm9taWMgb3V0cHV0IHBlciBwZXJzb24sIG1pcnJvcnMgdGhlIGZpbmFuY2lhbCBwcm9zcGVyaXR5IG9mIGEgbmF0aW9uJ3MgY2l0aXplbnMuCgpUaGlzIHByb2plY3QgaW52ZXN0aWdhdGVzIGludG8gdGhlIGludHJpY2F0ZSBjb25uZWN0aW9uIGJldHdlZW4gdHdvIHZpdGFsIGFzcGVjdHMgb2YgYSBjb3VudHJ5J3Mgd2VsbC1iZWluZzogbGlmZSBleHBlY3RhbmN5IGFuZCBHRFAgcGVyIGNhcGl0YS4gSW5zcGlyZWQgYnkgdGhlIGltcGFjdGZ1bCBHYXBtaW5kZXIgcHJvamVjdCwgY28tZm91bmRlZCBieSB0aGUgZXN0ZWVtZWQgSGFucyBSb3NsaW5nLFtsaW5rXShodHRwczovL3d3dy55b3V0dWJlLmNvbS93YXRjaD92PWhWaW1Wemd0RDZ3KSBhIGxlYWRpbmcgZmlndXJlIGluIHN0YXRpc3RpY3MgYW5kIHB1YmxpYyBoZWFsdGgsIHRoaXMgdmVudHVyZSBsZXZlcmFnZXMgdGhlIGV4dGVuc2l2ZSBhbmQgZ2xvYmFsbHkgZGl2ZXJzZSBHYXBtaW5kZXIgZGF0YXNldC4gVGhyb3VnaCBSb3NsaW5nJ3MgY29tcGVsbGluZyBwcmVzZW50YXRpb25zLCB0aGlzIGRhdGFzZXQgaGFzIGJlY29tZSBpbnN0cnVtZW50YWwgaW4gcG9wdWxhcml6aW5nIG5hcnJhdGl2ZXMgZ3JvdW5kZWQgaW4gZGF0YSwgZXNwZWNpYWxseSBjb25jZXJuaW5nIGdsb2JhbCBkZXZlbG9wbWVudC4KClRoZSBHYXBtaW5kZXIgZGF0YXNldCwgYSBjb21wcmVoZW5zaXZlIHJlcG9zaXRvcnkgb2YgaW5mb3JtYXRpb24gY29sbGVjdGVkIGZyb20gZGl2ZXJzZSBjb3VudHJpZXMgb3ZlciB0aGUgeWVhcnMsIHNlcnZlcyBhcyBhbiBpZGVhbCByZXNvdXJjZSBmb3IgZXhwbG9yaW5nIHNvY2lvLWVjb25vbWljIGluZGljYXRvcnMuIFdoaWxlIEdhcG1pbmRlciBpcyByZW5vd25lZCBmb3IgaXRzIGJyb2FkIHNjb3BlLCBpdCdzIGltcG9ydGFudCB0byBub3RlIHRoYXQgZm9yIHRoaXMgcHJvamVjdCwgSSdtIHV0aWxpemluZyBhIGRhdGFzZXQgc291cmNlZCBmcm9tIHRoZSBXb3JsZCBCYW5rLiBUaGlzIGRhdGFzZXQgZW5jYXBzdWxhdGVzIGRhdGEgZnJvbSB2YXJpb3VzIGNvdW50cmllcywgb2ZmZXJpbmcgYSBsb25naXR1ZGluYWwgcGVyc3BlY3RpdmUgc3Bhbm5pbmcgbXVsdGlwbGUgeWVhcnMsIGN1bG1pbmF0aW5nIGluIDIwMTguW0dhcG1pbmRlciBXZWJzaXRlXShodHRwczovL3d3dy5nYXBtaW5kZXIub3JnLykKCgpJbiBkZWx2aW5nIGludG8gdGhlIGludHJpY2F0ZSBmYWN0b3JzIGluZmx1ZW5jaW5nIGxpZmUgZXhwZWN0YW5jeSwgc3VjaCBhcyBoYXBwaW5lc3MsIHBvbGx1dGlvbiwgdGVycm9yaXNtLCBhbmQgZGlzZWFzZXMsIG15IHByaW1hcnkgZm9jdXMgaGFzIGJlZW4gb24gYSBzcGVjaWZpYyBhc3BlY3QsIHRoZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIGxpZmUgZXhwZWN0YW5jeSBhbmQgdGhlIEdEUCBwZXIgY2FwaXRhIG9mIGVhY2ggY291bnRyeS4gVGhlIHJlc3VsdHMgdW5kZXJzY29yZSBhIG5vdGFibGUgdHJlbmQg4oCTIGNvdW50cmllcyB3aXRoIGEgaGlnaGVyIEdEUCBwZXIgY2FwaXRhIGdlbmVyYWxseSBleGhpYml0IGEgc3VwZXJpb3IgbGlmZSBleHBlY3RhbmN5IGZvciB0aGVpciBjaXRpemVucywgc3VycGFzc2luZyBvdXRjb21lcyBvYnNlcnZlZCBpbiBjb3VudHJpZXMgd2l0aCBhIGxvd2VyIEdEUCBwZXIgY2FwaXRhIFtAOTU3OTU5NF0uCgpUaGUgb3V0Y29tZXMgYW5kIGluc2lnaHRzIGRlcml2ZWQgZnJvbSB0aGlzIHByb2plY3QgYXJlIGludGVuZGVkIHRvIHNoaW5lIGEgbGlnaHQgb24gdGhlIGZhY3RvcnMgaW1wYWN0aW5nIGxpZmUgZXhwZWN0YW5jeSB3b3JsZHdpZGUuIFRoZXNlIGZpbmRpbmdzIGFpbSB0byBwcm92aWRlIGd1aWRhbmNlIGZvciBwb2xpY3kgZGVjaXNpb25zLCBpbmZvcm0gc29jaW8tZWNvbm9taWMgc3RyYXRlZ2llcywgYW5kIHNoYXBlIHB1YmxpYyBoZWFsdGggaW5pdGlhdGl2ZXMuIEVtcGxveWluZyBhIGNvbXByZWhlbnNpdmUgYXBwcm9hY2gsIHRoaXMgcHJvamVjdCBzZWVrcyB0byBjb250cmlidXRlIHZhbHVhYmxlIHBlcnNwZWN0aXZlcyB0byB0aGUgb25nb2luZyBkaXNjdXNzaW9ucyByZWdhcmRpbmcgdGhlIGNvbXBsZXggcmVsYXRpb25zaGlwIGJldHdlZW4gZWNvbm9taWMgcHJvc3Blcml0eSBhbmQgbGlmZSBleHBlY3RhbmN5IGluIGRpdmVyc2UgZ2xvYmFsIHNldHRpbmdzLgoKIyBQcm9ibGVtIFN0YXRlbWVudAoKVGhlIHByaW1hcnkgZ29hbCBvZiB0aGlzIHByb2plY3QgaXMgdG8gdW5yYXZlbCBob3cgbGlmZSBleHBlY3RhbmN5IGNvcnJlbGF0ZXMgd2l0aCB0aGUgZWNvbm9taWMgcHJvc3Blcml0eSBvZiBuYXRpb25zLiBCeSBleGFtaW5pbmcgdGhpcyByZWxhdGlvbnNoaXAsIEkgYWltIHRvIGdhaW4gaW5zaWdodHMgaW50byB0aGUgZHluYW1pY3MgdGhhdCBzaGFwZSB0aGUgd2VsbC1iZWluZyBvZiBwb3B1bGF0aW9ucyBhY3Jvc3MgZGlmZmVyZW50IGNvdW50cmllcy4gVGhyb3VnaCBkYXRhLWRyaXZlbiBtZXRob2RvbG9naWVzIGFuZCBtYWNoaW5lIGxlYXJuaW5nIG1vZGVscywgdGhpcyBwcm9qZWN0IGVuZGVhdm9ycyB0byBjb250cmlidXRlIG1lYW5pbmdmdWwgcGVyc3BlY3RpdmVzIHRvIHRoZSBvbmdvaW5nIGRpc2NvdXJzZSBvbiBnbG9iYWwgZGV2ZWxvcG1lbnQuCgoKIyBEYXRhIENvbGxlY3Rpb24gYW5kIFByZS1wcm9jZXNzaW5nCgpJbiB0aGlzIHByb2plY3QgZGF0YXNldHMgc291cmNlZCBmcm9tIHRoZSBXb3JsZCBCYW5rIGZvciB0aGUgYW5hbHlzaXMuIFRvIGRldGVybWluZSBhIHN1aXRhYmxlIHNhbXBsZSBwZXJpb2QsIEkgc2NydXRpbml6ZWQgdGhlIGRhdGEgdG8gaWRlbnRpZnkgcGVyaW9kcyB3aXRoIG1pbmltYWwgbWlzc2luZyB2YWx1ZXMuIENvbnNlcXVlbnRseSwgSSBjaG9zZSB0aGUgZXhwYW5zaXZlIHRpbWVmcmFtZSBzcGFubmluZyBmcm9tIDE5NjAgdG8gMjAxOCBhY3Jvc3MgMTkzIGNvdW50cmllcy4gRHVyaW5nIGRhdGEgcHJlcHJvY2Vzc2luZywgSSByZW1vdmVkIG9ic2VydmF0aW9ucyB0aGF0IGRpZCBub3QgcGVydGFpbiB0byBpbmRpdmlkdWFsIGNvdW50cmllcywgcHJpbWFyaWx5IGZvY3VzaW5nIG9uIGVsaW1pbmF0aW5nIHJlZ2lvbmFsIGFuZCBnbG9iYWwgYXZlcmFnZXMgdG8gbWFpbnRhaW4gZGF0YSBpbnRlZ3JpdHkgYW5kIGFjY3VyYWN5LiBbV29ybGQgQmFua2QgRGF0YV0oaHR0cHM6Ly9kYXRhLndvcmxkYmFuay5vcmcpCgpUaGUgaW5pdGlhbCBzdGVwIGluIGFuYWx5emluZyB0aGUgY29sbGVjdGVkIGRhdGFzZXQgaW52b2x2ZWQgbWV0aWN1bG91cyBwcmUtcHJvY2Vzc2luZy4gRGF0YSBwcmUtcHJvY2Vzc2luZyBpcyBlc3NlbnRpYWwgYXMgaXQgcmVhZGllcyB0aGUgZGF0YXNldCBmb3IgYW5hbHlzaXMgb3IgbW9kZWwgZGV2ZWxvcG1lbnQuIFRoaXMgcHJvY2VzcyBpbmNsdWRlcyB0cmFuc2Zvcm1pbmcgdGhlIGRhdGEgaW50byB1c2FibGUgZm9ybWF0cyBhbmQgcmVjdGlmeWluZyBpcnJlZ3VsYXJpdGllcywgc3VjaCBhcyBOYU4gdmFsdWVzLCB3aGljaCBjYW4gc2lnbmlmaWNhbnRseSBpbXBhY3QgcmVzdWx0IGFjY3VyYWN5LgoKVGhlIGRhdGFzZXQgZXh0cmFjdGVkIGZvciB0aGlzIHN0dWR5IHdhcyBpbiB0aGUgZGVzaXJlZCBDU1YgZm9ybWF0LiBIb3dldmVyLCBpdCBkaWQgY29udGFpbiBtaXNzaW5nIG9yIHVuaWRlbnRpZmllZCB2YWx1ZXMuIERhdGFzZXRzIHdpdGggdGhlc2UgZ2FwcyBjYW4gY29tcHJvbWlzZSB0aGUgcHJlY2lzaW9uIG9mIGRhdGEgYW5hbHlzaXMgYW5kIG1vZGVsIHByZWRpY3Rpb25zLiBDb25zZXF1ZW50bHksIHRoaXMgcmVzZWFyY2ggdG9vayB0aGUgYXBwcm9hY2ggb2YgcmVtb3ZpbmcgYWxsIGluc3RhbmNlcyB3aXRoIG1pc3NpbmcgdmFsdWVzLCBsZWFkaW5nIHRvIHRoZSBlbGltaW5hdGlvbiBvZiBhcHByb3hpbWF0ZWx5IDQ0JSBvZiB0aGUgZGF0YXNldC4gQWRkaXRpb25hbGx5LCBpcnJlbGV2YW50IGFuZCByZWR1bmRhbnQgYXR0cmlidXRlcyB3ZXJlIGRyb3BwZWQgZHVyaW5nIHRoZSBhbmFseXNpcy4KCmBgYHtyLCBlY2hvPUZBTFNFLCByZXN1bHRzPSdoaWRlJ30KCmRhdGEgPC0gcmVhZC5jc3YoIkxpZmUgRXhwZWN0YW5jeSB2cyBHRFAuY3N2IiwgaGVhZGVyID0gVFJVRSkKCiNoZWFkKGRhdGEpICAjIFRvIHNlZSB0aGUgZmlyc3QgZmV3IHJvd3Mgb2YgdGhlIGRhdGFzZXQKI3RhaWwoZGF0YSkKI3N1bW1hcnkoZGF0YSkKCmBgYAoKYGBge3IsZWNobz1GQUxTRSxyZXN1bHRzPSdoaWRlJ30KCiMgQ2hlY2sgdGhlIGN1cnJlbnQgY29sdW1uIG5hbWVzCiNwcmludChjb2xuYW1lcyhkYXRhKSkKCgojIENoYW5nZSB0aGUgY29sdW1uIG5hbWUgZnJvbSAnR0RQLnBhciBDYXAnIHRvICdHRFAnCmNvbG5hbWVzKGRhdGEpW2NvbG5hbWVzKGRhdGEpID09ICJHRFAucGVyLmNhcGl0YSJdIDwtICJnZHBfcGVyX2NhcGl0YSIKCiMgQ2hhbmdlIHRoZSBjb2x1bW4gbmFtZSBmcm9tICdHRFAucGFyIENhcCcgdG8gJ0dEUCcKY29sbmFtZXMoZGF0YSlbY29sbmFtZXMoZGF0YSkgPT0gIkxpZmUuZXhwZWN0YW5jeSJdIDwtICJMaWZlRXhwIgoKY29sbmFtZXMoZGF0YSlbY29sbmFtZXMoZGF0YSkgPT0gIlBvcHVsYXRpb24uLmhpc3RvcmljYWwuZXN0aW1hdGVzLiJdIDwtICJwb3AiCgoKY29sbmFtZXMoZGF0YSlbY29sbmFtZXMoZGF0YSkgPT0gIkVudGl0eSJdIDwtICJjb3VudHJ5Igpjb2xuYW1lcyhkYXRhKVtjb2xuYW1lcyhkYXRhKSA9PSAiQ29udGluZW50Il0gPC0gImNvbnRpbmVudCIKY29sbmFtZXMoZGF0YSlbY29sbmFtZXMoZGF0YSkgPT0gIlllYXIiXSA8LSAieWVhciIKCiMgVmVyaWZ5IHRoZSBjaGFuZ2VzCiNwcmludChjb2xuYW1lcyhkYXRhKSkKCiMgUmVtb3ZlIG1pc3NpbmcgdmFsdWVzIChpZiBhbnkpCiNkYXRhIDwtIG5hLm9taXQoZGF0YSkKCgpgYGAKCiMjIERhdGEgU3BsaXR0aW5nCgpCZWZvcmUgYnVpbGRpbmcgYW55IG1vZGVsIGl0J3MgZXNzZW50aWFsIHRvIHByZXByb2Nlc3MgdGhlIGRhdGEuIEluIHRoaXMgY2FzZSwgd2Ugd2lsbCBzcGxpdCB0aGUgZGF0YSBpbnRvIHRyYWluaW5nIGFuZCB0ZXN0aW5nIHNldHMsIDcwJSBmb3IgdHJhaW5pbmcgYW5kIDMwJSBmb3IgdGVzdGluZy4KYGBge3IsZWNobz1GQUxTRSxyZXN1bHRzPSdoaWRlJ30KCiMgU2V0IHRoZSBzcGxpdCBwb2ludCAoZS5nLiwgNzAlIGZvciB0cmFpbmluZywgMzAlIGZvciB0ZXN0aW5nKQpzcGxpdF9wb2ludCA8LSBmbG9vcigwLjcgKiBucm93KGRhdGEpKQoKIyBTcGxpdCB0aGUgZGF0YSBpbnRvIHRyYWluaW5nIGFuZCB0ZXN0aW5nIHNldHMKdHJhaW5fZGF0YSA8LSBkYXRhWzE6c3BsaXRfcG9pbnQsIF0KdGVzdF9kYXRhIDwtIGRhdGFbKHNwbGl0X3BvaW50ICsgMSk6bnJvdyhkYXRhKSwgXQpgYGAKCiMgTWV0aG9kcwoKVmlzdWFsaXphdGlvbiBwbGF5cyBhIGNydWNpYWwgcm9sZSBpbiB0aGlzIGV4cGxvcmF0aW9uLCBpbGx1c3RyYXRpbmcgdGhlIHRlbXBvcmFsIGV2b2x1dGlvbiBvZiBsaWZlIGV4cGVjdGFuY3kgYWNyb3NzIGRpZmZlcmVudCBjb3VudHJpZXMgdGhyb3VnaG91dCB0aGUgeWVhcnMuIFRocm91Z2ggZHluYW1pYyB2aXN1YWxpemF0aW9ucywgdGhpcyBwcm9qZWN0IHdpbGwgaGlnaGxpZ2h0IGdsb2JhbCB0cmVuZHMgaW4gbGlmZSBleHBlY3RhbmN5LCBpZGVudGlmeWluZyBwYXR0ZXJucyBhbmQgdmFyaWF0aW9ucyBhY3Jvc3MgY29udGluZW50cyBhbmQgcmVnaW9ucy4gSSdsbCBhbHNvIGxvb2sgYXQgdGhlIG51bWJlcnMgdG8gc2VlIGlmIHRoZXJlJ3MgYSBzdHJvbmcgY29ubmVjdGlvbiBiZXR3ZWVuIGhvdyBtdWNoIG1vbmV5IGEgY291bnRyeSBtYWtlcyBhbmQgaG93IGxvbmcgcGVvcGxlIGxpdmUuIFRoZSBpbnZlc3RpZ2F0aW9uIGV4cGFuZHMgZnVydGhlciB3aXRoIHRoZSB1c2Ugb2YgYm94IHBsb3RzLCBwcm92aWRpbmcgaW5zaWdodHMgaW50byBob3cgbGlmZSBleHBlY3RhbmN5IHZhcmllcyBjb250aW5lbnQtd2lzZSwgYWRkaW5nIGEgbGF5ZXIgb2YgZGV0YWlsIHRvIHRoZSBhbmFseXNpcy4KCgpJbiBvcmRlciB0byBnYXVnZSB0aGUgaW50cmljYXRlIGNvbm5lY3Rpb24gYmV0d2VlbiBsaWZlIGV4cGVjdGFuY3kgYW5kIEdEUCBwZXIgY2FwaXRhLCAKVG8gbWVhc3VyZSB0aGUgY29ubmVjdGlvbiBiZXR3ZWVuIGxpZmUgZXhwZWN0YW5jeSBhbmQgR0RQIHBlciBjYXBpdGEsIEkgd2lsbCBjb25kdWN0IGEgbXVsdGlmYWNldGVkIHN0YXRpc3RpY2FsIGFuYWx5c2lzLiBUaGUgbWV0aG9kb2xvZ3kgaW5jbHVkZXMgaHlwb3RoZXNpcyB0ZXN0aW5nLCBMaW5lYXIgUmVncmVzc2lvbiBBbmFseXNpcywgYW5kIFJhbmRvbSBGb3Jlc3QgbW9kZWxpbmcuIFRoZSByZXN1bHRzIGRlcml2ZWQgZnJvbSB0aGVzZSB0d28gbWV0aG9kcyB3aWxsIGJlIHJpZ29yb3VzbHkgY29tcGFyZWQgd2l0aCB0aG9zZSBvYnRhaW5lZCB0aHJvdWdoIHRoZSB1dGlsaXphdGlvbiBvZiBTdXBwb3J0IFZlY3RvciBNYWNoaW5lIGFuZCBHcmFkaWVudCBCb29zdGluZyB0ZWNobmlxdWVzLiBBZGRpdGlvbmFsbHksIEkgd2lsbCB1c2UgY29ycmVsYXRpb24gYW5hbHlzaXMgdG8gcmV2ZWFsIHRoZSBzdHJlbmd0aCBhbmQgZGlyZWN0aW9uIG9mIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBsaWZlIGV4cGVjdGFuY3kgYW5kIEdEUCBwZXIgY2FwaXRhLiBUaGlzIGNvbXByZWhlbnNpdmUgYXBwcm9hY2ggYWltcyB0byBwcm92aWRlIGEgdGhvcm91Z2ggdW5kZXJzdGFuZGluZyBvZiBob3cgdGhlc2UgdHdvIGZhY3RvcnMgYXJlIGxpbmtlZC4gRXZhbHVhdGlvbiBtZXRyaWNzIGxpa2UgUi1zcXVhcmVkIGFuZCBSb290IE1lYW4gU3F1YXJlZCBFcnJvciAoUk1TRSkgd2lsbCBiZSB1dGlsaXplZCB0byBjb21wYXJlIHRoZSBwZXJmb3JtYW5jZSBvZiB0aGVzZSBtb2RlbHMsIHByb3ZpZGluZyBhIGNvbXByZWhlbnNpdmUgdW5kZXJzdGFuZGluZyBvZiB0aGVpciBwcmVkaWN0aXZlIGNhcGFiaWxpdGllcy4KClRoZSByZXN1bHRzIGFuZCBjb25jbHVzaW9ucyBkcmF3biBmcm9tIHRoaXMgcHJvamVjdCBhaW0gdG8gaWxsdW1pbmF0ZSB0aGUgZmFjdG9ycyBpbmZsdWVuY2luZyBnbG9iYWwgbGlmZSBleHBlY3RhbmN5LCBvZmZlcmluZyBpbnNpZ2h0cyB0aGF0IGNhbiBndWlkZSBwb2xpY3kgZGVjaXNpb25zLCBpbmZvcm0gc29jaW8tZWNvbm9taWMgc3RyYXRlZ2llcywgYW5kIHNoYXBlIHB1YmxpYyBoZWFsdGggaW5pdGlhdGl2ZXMuIFRocm91Z2ggYSBtdWx0aWZhY2V0ZWQgYXBwcm9hY2gsIHRoaXMgcHJvamVjdCBhc3BpcmVzIHRvIGNvbnRyaWJ1dGUgbWVhbmluZ2Z1bCBwZXJzcGVjdGl2ZXMgdG8gdGhlIG9uZ29pbmcgZGlzY291cnNlIG9uIHRoZSBpbnRyaWNhdGUgaW50ZXJwbGF5IGJldHdlZW4gZWNvbm9taWMgcHJvc3Blcml0eSBhbmQgbGlmZSBleHBlY3RhbmN5IGFjcm9zcyBkaXZlcnNlIGdsb2JhbCBjb250ZXh0cy4KCiMjIENob3JvcGxldGggTWFwCgpBIGNob3JvcGxldGggbWFwIGlzIGEgdHlwZSBvZiB0aGVtYXRpYyBtYXAgdGhhdCB1c2VzIGNvbG9ycyBvciBzaGFkaW5nIHRvIHJlcHJlc2VudCBzdGF0aXN0aWNhbCBkYXRhIGFjcm9zcyBnZW9ncmFwaGljIHJlZ2lvbnMgb3IgYXJlYXMuIFRoZSBpbnRlbnNpdHkgb2YgY29sb3Igb3Igc2hhZGluZyB2YXJpZXMgYmFzZWQgb24gdGhlIG1hZ25pdHVkZSBvZiB0aGUgZGF0YSBiZWluZyByZXByZXNlbnRlZCwgYWxsb3dpbmcgdmlld2VycyB0byBxdWlja2x5IGdyYXNwIHBhdHRlcm5zIG9yIHZhcmlhdGlvbnMuCgpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSIxMDAlIn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi9Vc2Vycy9zaGFtaW1hL0Rlc2t0b3AvUHJvamVjdF8xL2ltYWdlcy9uZXdwbG90LnBuZyIsIGVycm9yID0gRkFMU0UpCgpgYGAKClRoZSBhYm92ZSBjaG9yb3BsZXRoIG1hcCBpcyB2aXN1YWxpemluZyAgbGlmZSBleHBlY3RhbmN5IGRhdGEgYWNyb3NzIGRpZmZlcmVudCBjb3VudHJpZXMgb3IgcmVnaW9ucyBpbiB0aGUgeWVhciAyMDE4LiBEYXJrZXIgb3IgbW9yZSBpbnRlbnNlIGNvbG9ycyBtYXkgcmVwcmVzZW50IGhpZ2hlciBsaWZlIGV4cGVjdGFuY3ksIHdoaWxlIGxpZ2h0ZXIgY29sb3JzIGluZGljYXRlIGxvd2VyIGxpZmUgZXhwZWN0YW5jeS4gVGhpcyB0eXBlIG9mIG1hcCBwcm92aWRlcyBhIHZpc3VhbCBzdW1tYXJ5IG9mIHRoZSBkaXN0cmlidXRpb24gb2YgbGlmZSBleHBlY3RhbmN5LCBtYWtpbmcgaXQgZWFzaWVyIHRvIGlkZW50aWZ5IGdsb2JhbCB0cmVuZHMgYW5kIGRpc3Bhcml0aWVzLlRoaXMgbWFwIGlzIGEgcG93ZXJmdWwgdG9vbCBmb3IgdW5kZXJzdGFuZGluZyBob3cgd2VsbC1iZWluZyBpcyBkaXN0cmlidXRlZCBnZW9ncmFwaGljYWxseSwgaGlnaGxpZ2h0aW5nIGNsZWFyIGRpZmZlcmVuY2VzIGJldHdlZW4gY291bnRyaWVzIGFuZCBjb250aW5lbnRzLiAKCgojIyBTY2F0dGVyIFBsb3QgZm9yIExpZmUgRXhwZWN0YW5jeSB2cyBHRFAgcGVyIENhcGl0YQoKQSBzY2F0dGVyIHBsb3QgaXMgdXNlZnVsIGZvciBpZGVudGlmeWluZyB0cmVuZHMsIGNvcnJlbGF0aW9ucywgb3IgcGF0dGVybnMgaW4gdGhlIGRhdGEuIEluIHRoZSBiZWxsb3cgc2NhdHRlciBwbG90IGlzIGEgZ3JhcGhpY2FsIHJlcHJlc2VudGF0aW9uIHRoYXQgZGlzcGxheXMgaW5kaXZpZHVhbCBkYXRhIHBvaW50cyBmb3IgZWFjaCBjb3VudHJ5LgoKYGBge3IsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iMTAwJSJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIvVXNlcnMvc2hhbWltYS9EZXNrdG9wL1Byb2plY3RfMS9pbWFnZXMvU2NhdHRlclBsb3QucG5nIiwgZXJyb3IgPSBGQUxTRSkKCmBgYAoKVGhlIHNjYXR0ZXIgcGxvdCB2aXN1YWxseSByZXByZXNlbnRpbmcgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGxpZmUgZXhwZWN0YW5jeSBhbmQgR0RQIHBlciBjYXBpdGEgaW4geWVhciBvZiAyMDE4LCBvZmZlcmluZyBhIGNvbXBlbGxpbmcgaW5zaWdodCBpbnRvIGhvdyB0aGUgZWNvbm9taWMgcHJvc3Blcml0eSBvZiBhIGNvdW50cnkgY29ycmVsYXRlcyB3aXRoIHRoZSBsaWZlIGV4cGVjdGFuY3kgb2YgaXRzIGNpdGl6ZW5zLiBBcyB3ZSBleGFtaW5lIHRoZSBzY2F0dGVyIHBsb3QsIGEgZGlzY2VybmlibGUgcGF0dGVybiBlbWVyZ2Vz4oCUY291bnRyaWVzIHdpdGggaGlnaGVyIEdEUCBwZXIgY2FwaXRhIHRlbmQgdG8gZXhoaWJpdCBpbmNyZWFzZWQgbGlmZSBleHBlY3RhbmN5LgoKRWFjaCBwb2ludCBvbiB0aGUgcGxvdCBjb3JyZXNwb25kcyB0byBhIHNwZWNpZmljIGNvdW50cnksIHdpdGggdGhlIHgtYXhpcyByZXByZXNlbnRpbmcgdGhlIEdEUCBwZXIgY2FwaXRhIGFuZCB0aGUgeS1heGlzIHJlcHJlc2VudGluZyBsaWZlIGV4cGVjdGFuY3kuIFRoZSB1cHdhcmQgdHJlbmQgb2JzZXJ2ZWQgaW4gdGhlIHNjYXR0ZXJwbG90IHN1Z2dlc3RzIGEgcG9zaXRpdmUgYXNzb2NpYXRpb24gYmV0d2VlbiB0aGVzZSB0d28gdmFyaWFibGVzLiBJbiBzaW1wbGVyIHRlcm1zLCBhcyBhIGNvdW50cnkncyBHRFAgcGVyIGNhcGl0YSBpbmNyZWFzZXMsIHRoZXJlIGlzIGEgbm90YWJsZSByaXNlIGluIGxpZmUgZXhwZWN0YW5jeS4KClRoaXMgcmVsYXRpb25zaGlwIHVuZGVyc2NvcmVzIHRoZSBwb3RlbnRpYWwgaW1wYWN0IG9mIGVjb25vbWljIHdlbGwtYmVpbmcgb24gdGhlIG92ZXJhbGwgaGVhbHRoIGFuZCBsb25nZXZpdHkgb2YgYSBwb3B1bGF0aW9uLiBUaGUgc2NhdHRlcnBsb3Qgc2VydmVzIGFzIGEgdmlzdWFsIG5hcnJhdGl2ZSwgaGlnaGxpZ2h0aW5nIHRoZSB0cmVuZCBhbmQgcmVpbmZvcmNpbmcgdGhlIG5vdGlvbiB0aGF0IGhpZ2hlciBlY29ub21pYyBwcm9zcGVyaXR5IGNvbnRyaWJ1dGVzIHBvc2l0aXZlbHkgdG8gdGhlIGxpZmUgZXhwZWN0YW5jeSBvZiBhIGNvdW50cnkncyByZXNpZGVudHMuCgojIyBCb3ggUGxvdHMKCkEgYm94IHBsb3QgaXMgYSBncmFwaGljYWwgcmVwcmVzZW50YXRpb24gb2YgdGhlIGRpc3RyaWJ1dGlvbiBvZiBhIGRhdGFzZXQuIEl0IHByb3ZpZGVzIGEgdmlzdWFsIHN1bW1hcnkgb2Yga2V5IHN0YXRpc3RpY2FsIG1lYXN1cmVzIGFuZCBhbGxvdyB0byB1bmRlcnN0YW5kIHRoZSBjZW50cmFsIHRlbmRlbmN5LCBzcHJlYWQsIGFuZCBpZGVudGlmeSBwb3RlbnRpYWwgb3V0bGllcnMgd2l0aGluIHRoZSBkYXRhLgoKSGVyZSBpbiB0aGlzIHByb2plY3QgdGhlIGJveCBwbG90IHNob3djYXNpbmcgbGlmZSBleHBlY3RhbmN5IGRhdGEgYnkgY29udGluZW50IHByb3ZpZGVzIGEgY29uY2lzZSBhbmQgaW5zaWdodGZ1bCB2aXN1YWxpemF0aW9uIG9mIHRoZSBkaXN0cmlidXRpb24gYW5kIGNlbnRyYWwgdGVuZGVuY2llcyBvZiBsaWZlIGV4cGVjdGFuY3kgYWNyb3NzIGRpZmZlcmVudCByZWdpb25zLiBFYWNoIGJveCByZXByZXNlbnRzIGEgY29udGluZW50LCBkaXNwbGF5aW5nIHRoZSBpbnRlcnF1YXJ0aWxlIHJhbmdlICwgbWVkaWFuLCBhbmQgcG90ZW50aWFsIG91dGxpZXJzIEBkZXZvcmUyMDE1cHJvYmFiaWxpdHkuCgpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSIxMDAlIn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi9Vc2Vycy9zaGFtaW1hL0Rlc2t0b3AvUHJvamVjdF8xL2ltYWdlcy8wMDAwMTAucG5nIiwgZXJyb3IgPSBGQUxTRSkKa25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi9Vc2Vycy9zaGFtaW1hL0Rlc2t0b3AvUHJvamVjdF8xL2ltYWdlcy8wMDAwMTMucG5nIiwgZXJyb3IgPSBGQUxTRSkKCmBgYAoKVGhlIGJveCBwbG90IHZpc3VhbGl6aW5nIEdEUCBwZXIgY2FwaXRhIGJ5IGNvbnRpbmVudCwgYSBjb21wZWxsaW5nIHRyZW5kIGVtZXJnZXMgYXMgaGlnaGVyIEdEUCBsZXZlbHMgYXJlIGFzc29jaWF0ZWQgd2l0aCBpbmNyZWFzZWQgTGlmZSBFeHBlY3RhbmN5LiBUaGUgYm94ZXMgY29uc2lzdGVudGx5IHNoaWZ0IHVwd2FyZHMgYWNyb3NzIGNvbnRpbmVudHMgd2l0aCBoaWdoZXIgR0RQLCBpbmRpY2F0aW5nIGEgcG9zaXRpdmUgY29ycmVsYXRpb24gYmV0d2VlbiBlY29ub21pYyBwcm9zcGVyaXR5IGFuZCB0aGUgb3ZlcmFsbCB3ZWxsLWJlaW5nIG9mIHBvcHVsYXRpb25zLiBUaGlzIG9ic2VydmF0aW9uIHN1Z2dlc3RzIHRoYXQgY291bnRyaWVzIHdpdGggaGlnaGVyIEdEUCBwZXIgY2FwaXRhIHRlbmQgdG8gZXhoaWJpdCBub3Qgb25seSBzdHJvbmdlciBlY29ub21pYyBwZXJmb3JtYW5jZSBidXQgYWxzbyBlbGV2YXRlZCBsaWZlIGV4cGVjdGFuY2llcywgcHJvdmlkaW5nIHZhbHVhYmxlIGluc2lnaHRzIGludG8gdGhlIGludGVyY29ubmVjdGVkIGR5bmFtaWNzIG9mIGVjb25vbWljIGRldmVsb3BtZW50IGFuZCBwdWJsaWMgaGVhbHRoIG9uIGEgZ2xvYmFsIHNjYWxlLgoKIyMgSHlwb3RoZXNpcyBUZXN0CgpIeXBvdGhlc2lzIHRlc3RpbmcgZm9yIGNvcnJlbGF0aW9uIGludm9sdmVzIHRlc3Rpbmcgd2hldGhlciB0aGUgb2JzZXJ2ZWQgY29ycmVsYXRpb24gY29lZmZpY2llbnQgaXMgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgZnJvbSB6ZXJvLkluIHRoZSBjb250ZXh0IG9mIHRoaXMgcHJvamVjdCwgd2hlcmUgSSBhbSBleGFtaW5pbmcgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gbGlmZSBleHBlY3RhbmN5IGFuZCBHRFAgcGVyIGNhcGl0YSwgSSBhbSBmb2xsb3dpbmcgdGhlIHN0ZXBzIGZvciBoeXBvdGhlc2lzIHRlc3RpbmcuCgokJAp7SHlwb3RoZXNpc1wgVGVzdDp9IFxcClxiZWdpbnthbGlnbip9CiYgSF8wOiBcdGV4dHtUaGVyZSBpcyBubyBzaWduaWZpY2FudCBjb3JyZWxhdGlvbiBiZXR3ZWVuIGxpZmUgZXhwZWN0YW5jeSBhbmQgR0RQIHBlciBjYXBpdGEgKFwoXHJobyA9IDBcKSkufSBcXAomIEhfYTogXHRleHR7VGhlcmUgaXMgYSBzaWduaWZpY2FudCBjb3JyZWxhdGlvbiBiZXR3ZWVuIGxpZmUgZXhwZWN0YW5jeSBhbmQgR0RQIHBlciBjYXBpdGEgKFwoXHJobyBcbmVxIDBcKSkufQpcZW5ke2FsaWduKn0KJCQKCiQkCkludGVycHJldFwgUmVzdWx0czoKXGJlZ2lue2FsaWduKn0KJiBcdGV4dHtJZiBwLXZhbHVlfSA8IFxhbHBoYSwgXHRleHR7cmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMufSBcXAomIFx0ZXh0e0lmIHAtdmFsdWV9IFxnZXEgXGFscGhhLCBcdGV4dHtmYWlsIHRvIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzLn0KXGVuZHthbGlnbip9CiQkCgpgYGB7cixlY2hvPUZBTFNFfQoKIyBDYWxjdWxhdGUgQ29ycmVsYXRpb24gQ29lZmZpY2llbnQKY29ycmVsYXRpb25fY29lZmZpY2llbnQgPC0gY29yKGRhdGEkTGlmZUV4cCwgZGF0YSRnZHBfcGVyX2NhcGl0YSkKCiMgQ29uZHVjdCBIeXBvdGhlc2lzIFRlc3QKY29yX3Rlc3RfcmVzdWx0IDwtIGNvci50ZXN0KGRhdGEkTGlmZUV4cCwgZGF0YSRnZHBfcGVyX2NhcGl0YSkKCiMgSW50ZXJwcmV0IFJlc3VsdHMKY2F0KCJPYnNlcnZlZCBDb3JyZWxhdGlvbiBDb2VmZmljaWVudDoiLCBjb3JyZWxhdGlvbl9jb2VmZmljaWVudCwgIlxuIikKY2F0KCJwLXZhbHVlOiIsIGNvcl90ZXN0X3Jlc3VsdCRwLnZhbHVlLCAiXG4iKQoKIyBDaGVjayBpZiB0aGUgcC12YWx1ZSBpcyBsZXNzIHRoYW4gdGhlIHNpZ25pZmljYW5jZSBsZXZlbCAoZS5nLiwgMC4wNSkKaWYgKGNvcl90ZXN0X3Jlc3VsdCRwLnZhbHVlIDwgMC4wNSkgewogIGNhdCgiUmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMuIFRoZXJlIGlzIGEgc2lnbmlmaWNhbnQgY29ycmVsYXRpb24uXG4iKQp9IGVsc2UgewogIGNhdCgiRmFpbCB0byByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcy4gVGhlcmUgaXMgbm90IGVub3VnaCBldmlkZW5jZSBvZiBhIHNpZ25pZmljYW50IGNvcnJlbGF0aW9uLlxuIikKfQoKYGBgClRoZSBvYnNlcnZlZCBjb3JyZWxhdGlvbiBjb2VmZmljaWVudCBvZiAwLjYzNDIwNDQgaW5kaWNhdGVzIGEgbW9kZXJhdGUgdG8gc3Ryb25nIHBvc2l0aXZlIGNvcnJlbGF0aW9uIGJldHdlZW4gbGlmZSBleHBlY3RhbmN5IGFuZCBHRFAgcGVyIGNhcGl0YS4gVGhlIGV4dHJlbWVseSBsb3cgcC12YWx1ZSBzdWdnZXN0cyB0aGF0IHRoaXMgY29ycmVsYXRpb24gaXMgaGlnaGx5IHVubGlrZWx5IHRvIGhhdmUgb2NjdXJyZWQgYnkgcmFuZG9tIGNoYW5jZSBhbG9uZS4gVGhlcmVmb3JlLCB3ZSByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyBhbmQgY29uY2x1ZGUgdGhhdCB0aGVyZSBpcyBhIHNpZ25pZmljYW50IGNvcnJlbGF0aW9uIGJldHdlZW4gbGlmZSBleHBlY3RhbmN5IGFuZCBHRFAgcGVyIGNhcGl0YSBpbiB5b3VyIGRhdGFzZXQuCgoKIyMgQ29ycmVsYXRpb24gTWF0cml4CgpBIGNvcnJlbGF0aW9uIG1hdHJpeCBpcyBhIHN0YXRpc3RpY2FsIHRhYmxlIHRoYXQgZGlzcGxheXMgdGhlIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50cyBiZXR3ZWVuIHNldmVyYWwgdmFyaWFibGVzLiBJdCBpcyBhIHN5bW1ldHJpYyBtYXRyaXggd2hlcmUgZWFjaCBjZWxsIHJlcHJlc2VudHMgdGhlIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50IGJldHdlZW4gdHdvIHZhcmlhYmxlcy4gQ29ycmVsYXRpb24gY29lZmZpY2llbnRzIHF1YW50aWZ5IHRoZSBzdHJlbmd0aCBhbmQgZGlyZWN0aW9uIG9mIGEgbGluZWFyIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHR3byB2YXJpYWJsZXMuCgpUaGUgY29ycmVsYXRpb24gY29lZmZpY2llbnQgaXMgYSBudW1lcmljYWwgdmFsdWUgcmFuZ2luZyBmcm9tIC0xIHRvIDEuCkNvcnJlbGF0aW9uIG9mIDEgaW5kaWNhdGVzIGEgcGVyZmVjdCBwb3NpdGl2ZSBsaW5lYXIgcmVsYXRpb25zaGlwIGFuZCBjb3JyZWxhdGlvbiBvZiAtMSBpbmRpY2F0ZXMgYSBwZXJmZWN0IG5lZ2F0aXZlIGxpbmVhciwgY29ycmVsYXRpb24gb2YgMCBpbmRpY2F0ZXMgbm8gbGluZWFyIHJlbGF0aW9ucyBiZXR3ZWVuIHRoZSB2YXJpYWJsZXMuCgpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSIxMDAlIn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi9Vc2Vycy9zaGFtaW1hL0Rlc2t0b3AvUHJvamVjdF8xL2ltYWdlcy8wMDAwMTIucG5nIiwgZXJyb3IgPSBGQUxTRSkKCmBgYAoKVGhlIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50IGJldHdlZW4gTGlmZSBFeHBlY3RhbmN5IGFuZCBHRFAgcGVyIENhcGl0YSBpcyBhcHByb3hpbWF0ZWx5IDAuNjAuIFRoaXMgcG9zaXRpdmUgdmFsdWUgaW5kaWNhdGVzIGEgbW9kZXJhdGUgcG9zaXRpdmUgY29ycmVsYXRpb24sIHN1Z2dlc3RpbmcgdGhhdCBhcyBMaWZlIEV4cGVjdGFuY3kgdGVuZHMgdG8gaW5jcmVhc2UsIEdEUCBwZXIgQ2FwaXRhIGFsc28gdGVuZHMgdG8gaW5jcmVhc2UuIEluIHNpbXBsZXIgdGVybXMsIHRoZXJlIGlzIGEgdGVuZGVuY3kgZm9yIGNvdW50cmllcyB3aXRoIGhpZ2hlciBsaWZlIGV4cGVjdGFuY2llcyB0byBoYXZlIGhpZ2hlciBHRFAgcGVyIENhcGl0YS4KCiMgTW9kZWwgQnVpbGRpbmcgYW5kIFByZWRpY3Rpb24KCiMjIExpbm5lYXIgUmVncmVzc2lvbiBNb2RlbAoKTGluZWFyIFJlZ3Jlc3Npb24gaXMgYSBtYWNoaW5lIGxlYXJuaW5nIGFsZ29yaXRobSB1c2VkIHRvIG1vZGVsIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBhIGRlcGVuZGVudCB2YXJpYWJsZSBhbmQgb25lIG9yIG1vcmUgaW5kZXBlbmRlbnQgdmFyaWFibGVzLiBJdCBhc3N1bWVzIGEgbGluZWFyIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSB2YXJpYWJsZXMsIGFpbWluZyB0byBmaW5kIHRoZSBiZXN0LWZpdHRpbmcgbGluZSB0aGF0IG1pbmltaXplcyB0aGUgc3VtIG9mIHNxdWFyZWQgZGlmZmVyZW5jZXMgYmV0d2VlbiBvYnNlcnZlZCBhbmQgcHJlZGljdGVkIHZhbHVlcyBAbGFudHoyMDE5bWFjaGluZS4KCiQkCkxpbmVhclwgUmVncmVzc2lvblwgRXF1YXRpb246IFxcCiQkCgokJCAKWSA9IFxiZXRhXzAgKyBcYmV0YV8xIFhfMSArIFxiZXRhXzIgWF8yICsgXGxkb3RzICsgXGJldGFfbiBYX24gKyBcdmFyZXBzaWxvbiBcXAokJAoKCiQkCkluXCB0aGlzXCBlcXVhdGlvbjogXFwKJCQKJCQKWTogXHRleHR7RGVwZW5kZW50IHZhcmlhYmxlfVxcJCQKCiQkXGJldGFfMDogXHRleHR7WS1pbnRlcmNlcHQsIHRoZSBjb25zdGFudCB0ZXJtfVxcJCQKCiQkXGJldGFfMSwgXGJldGFfMiwgXGxkb3RzLCBcYmV0YV9uOiBcdGV4dHtDb2VmZmljaWVudHMgb2YgdGhlIGluZGVwZW5kZW50IHZhcmlhYmxlcyB9IChYXzEsIFhfMiwgXGxkb3RzLCBYX24pXFwkJAoKJCRYXzEsIFhfMiwgXGxkb3RzLCBYX246IFx0ZXh0e0luZGVwZW5kZW50IHZhcmlhYmxlc31cXCQkCgokJApcdmFyZXBzaWxvbjogXHRleHR7RXJyb3IgdGVybSwgcmVwcmVzZW50aW5nIHVub2JzZXJ2ZWQgZmFjdG9ycyBhZmZlY3RpbmcgdGhlIGRlcGVuZGVudCB2YXJpYWJsZS59CiQkCgpMaW5lYXIgcmVncmVzc2lvbiBtb2RlbCB0byBwcmVkaWN0IGxpZmUgZXhwZWN0YW5jeToKYGBge3IsZWNobz1GQUxTRX0KCiMgQnVpbGQgYSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbApsbV9tb2RlbCA8LSBsbShMaWZlRXhwIH4gZ2RwX3Blcl9jYXBpdGEsIGRhdGEgPSB0cmFpbl9kYXRhKQoKc3VtbWFyeShsbV9tb2RlbCkKCmBgYAoKSW4gdGhlIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsIHN1Z2dlc3RzIGEgc2lnbmlmaWNhbnQgcG9zaXRpdmUgcmVsYXRpb25zaGlwIGJldHdlZW4gR0RQIHBlciBjYXBpdGEgYW5kIGxpZmUgZXhwZWN0YW5jeS4gQWJvdXQgMzUlIG9mIHRoZSB2YXJpYW5jZSBpbiBsaWZlIGV4cGVjdGFuY3kgY2FuIGJlIGV4cGxhaW5lZCBieSBHRFAgcGVyIGNhcGl0YS4gVGhlIG1vZGVsJ3MgcHJlZGljdGlvbnMgYXJlIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgYW5kIHByb3ZpZGUgdmFsdWFibGUgaW5zaWdodHMgaW50byB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gZWNvbm9taWMgcHJvc3Blcml0eSBhbmQgbGlmZSBleHBlY3RhbmN5LgoKCgojIyMgTGluZWFyIFJlZ3Jlc3Npb24gU2NhdHRlciBQbG90IAoKYGBge3IsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iMTAwJSJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIvVXNlcnMvc2hhbWltYS9EZXNrdG9wL1Byb2plY3RfMS9pbWFnZXMvU2NhdHRlclBsb3RMLnBuZyIsIGVycm9yID0gRkFMU0UpCgpgYGAKClRoZSAgc2NhdHRlcnBsb3QgZm9yIExpbmVhciBSZWdyZXNzaW9uIHNob3dpbmcgdGhlIGNvbm5lY3Rpb24gYmV0d2VlbiBsaWZlIGV4cGVjdGFuY3kgYW5kIEdEUCBwZXIgY2FwaXRhIGFuIGludGVyZXN0aW5nIHBhdHRlcm4uIEluc3RlYWQgb2YgYSBzaW1wbGUgbGluZWFyIHRyZW5kLCB0aGUgcmVsYXRpb25zaGlwIHNlZW1zIHRvIGV4aGliaXQgYSBsb2dhcml0aG1pYyB0cmFqZWN0b3J5LiBUaGlzIGluZGljYXRlcyB0aGF0IHRoZSBpbmZsdWVuY2Ugb2YgYW4gaW5jcmVhc2UgaW4gR0RQIHBlciBjYXBpdGEgb24gbGlmZSBleHBlY3RhbmN5IHZhcmllcyBhY3Jvc3MgZGlmZmVyZW50IGVjb25vbWljIHNjZW5hcmlvcy4KCkluIHBvb3JlciBjb3VudHJpZXMgYW4gZWxldmF0aW9uIGluIEdEUCBwZXIgY2FwaXRhIHNlZW1zIHRvIHlpZWxkIGEgbW9yZSBzdWJzdGFudGlhbCBwb3NpdGl2ZSBlZmZlY3Qgb24gbGlmZSBleHBlY3RhbmN5IGNvbXBhcmVkIHRvIHdlYWx0aGllciBuYXRpb25zLiBUaGlzIHBoZW5vbWVub24gY2FuIGJlIHJhdGlvbmFsaXplZCBieSBjb25zaWRlcmluZyB0aGF0IGVjb25vbWljYWxseSBkaXNhZHZhbnRhZ2VkIGNvdW50cmllcyBtYXkgZXhwZXJpZW5jZSBzaWduaWZpY2FudCBpbXByb3ZlbWVudHMgaW4gbGlmZSBleHBlY3RhbmN5IHdoZW4gZmluYW5jaWFsIHJlc291cmNlcyBhcmUgZGlyZWN0ZWQgdG93YXJkcyBlbmhhbmNpbmcgaGVhbHRoY2FyZSBpbmZyYXN0cnVjdHVyZSBhbmQgbWVkaWNhbCB0cmVhdG1lbnRzLgoKIyMgUmFuZG9tIEZvcmVzdCBSZWdyZXNzb3IgTW9kZWwKCkluIG9yZGVyIHRvIGV4cGxvcmUgYSBtb3JlIGFkdmFuY2VkIGFwcHJvYWNoIHRvIHByZWRpY3QgbGlmZSBleHBlY3RhbmN5IGJhc2VkIG9uIEdEUCBwZXIgY2FwaXRhLiBJJ20gdXNpbmcgYSBSYW5kb20gRm9yZXN0IHJlZ3Jlc3Nvci4KClJhbmRvbSBGb3Jlc3QgaXMgYSBwb3dlcmZ1bCBlbnNlbWJsZSBsZWFybmluZyBhbGdvcml0aG0gdXNlZCBmb3IgYm90aCBjbGFzc2lmaWNhdGlvbiBhbmQgcmVncmVzc2lvbiB0YXNrcy4gSXQgd2FzIGludHJvZHVjZWQgYnkgTGVvIEJyZWltYW4gaW4gMjAwMS4gVGhlICJmb3Jlc3QiIGluIFJhbmRvbSBGb3Jlc3QgaXMgYSBjb2xsZWN0aW9uIG9mIGRlY2lzaW9uIHRyZWVzLCBhbmQgdGhlICJyYW5kb20iIHBhcnQgY29tZXMgZnJvbSB0aGUgZmFjdCB0aGF0IGVhY2ggdHJlZSBpcyB0cmFpbmVkIG9uIGEgcmFuZG9tIHN1YnNldCBvZiB0aGUgZGF0YSBhbmQgZmVhdHVyZXMuCgokJApcdGV4dHtSZWdyZXNzaW9uOn1cXCBcaGF0e3l9X3tcdGV4dHtSRn19ID0gXGZyYWN7MX17bn0gXHN1bV97aT0xfV57bn0gXGhhdHt5fV9pIAokJAoKJCQgClx0ZXh0e0NsYXNzaWZpY2F0aW9ufTogXFwKXGhhdHt5fV97XHRleHR7UkZ9fSA9IFx0ZXh0e21vZGV9KFxoYXR7eX1fMSwgXGhhdHt5fV8yLCBcbGRvdHMsIFxoYXR7eX1fbikKJCQKClJhbmRvbSBGb3Jlc3QgaXMgd2lkZWx5IHVzZWQgaW4gdmFyaW91cyBmaWVsZHMgZHVlIHRvIGl0cyB2ZXJzYXRpbGl0eSBhbmQgZWZmZWN0aXZlbmVzcyBpbiBwcm9kdWNpbmcgaGlnaC1xdWFsaXR5IHByZWRpY3Rpb25zLgoKYGBge3IsZWNobz1GQUxTRSxyZXN1bHRzPSdoaWRlJ30KCiMgTG9hZCBsaWJyYXJpZXMKbGlicmFyeShjYXJldCkKbGlicmFyeShyYW5kb21Gb3Jlc3QpCgojIEJ1aWxkIGEgUmFuZG9tIEZvcmVzdCBSZWdyZXNzb3IgbW9kZWwKcmZfbW9kZWwgPC0gcmFuZG9tRm9yZXN0KExpZmVFeHAgfiBnZHBfcGVyX2NhcGl0YSwgZGF0YSA9IHRyYWluX2RhdGEsIG50cmVlID0gMTAwKQoKIyBNYWtlIHByZWRpY3Rpb25zIG9uIHRoZSB0ZXN0IHNldAp0ZXN0X2RhdGEkcHJlZGljdGlvbnNfcmYgPC0gcHJlZGljdChyZl9tb2RlbCwgbmV3ZGF0YSA9IHRlc3RfZGF0YSkKCiMgQ2FsY3VsYXRlIFItc3F1YXJlZCBzY29yZSBmb3IgUmFuZG9tIEZvcmVzdApyZl9yX3NxdWFyZWQgPC0gMSAtIHN1bSgodGVzdF9kYXRhJExpZmVFeHAgLSB0ZXN0X2RhdGEkcHJlZGljdGlvbnNfcmYpXjIpIC8gc3VtKCh0ZXN0X2RhdGEkTGlmZUV4cCAtIG1lYW4odGVzdF9kYXRhJExpZmVFeHApKV4yKQpwcmludChwYXN0ZSgiUmFuZG9tIEZvcmVzdCBSLXNxdWFyZWQgU2NvcmU6ICIsIHJvdW5kKHJmX3Jfc3F1YXJlZCwgMikpKQoKIyBDYWxjdWxhdGUgUk1TRSBmb3IgUmFuZG9tIEZvcmVzdCBSZWdyZXNzb3IKcm1zZV9yZiA8LSBzcXJ0KG1lYW4oKHRlc3RfZGF0YSRwcmVkaWN0aW9uc19yZiAtIHRlc3RfZGF0YSRMaWZlRXhwKV4yKSkKcm1zZV9yZgoKIyBEaXNwbGF5IHRoZSBSYW5kb20gRm9yZXN0IG1vZGVsIGRldGFpbHMKcmZfbW9kZWwKYGBgClRoaXMgUmFuZG9tIEZvcmVzdCBtb2RlbCBpcyBzcGVjaWZpZWQgZm9yIHJlZ3Jlc3Npb24sIGluZGljYXRpbmcgdGhhdCBpdCBpcyBkZXNpZ25lZCB0byBwcmVkaWN0IGEgY29udGludW91cyBvdXRjb21lLCB3aGljaCBhbGlnbnMgd2l0aCB0aGUgbmF0dXJlIG9mIHRoZSBsaWZlIGV4cGVjdGFuY3kgdmFyaWFibGUuCgpUaGUgUmFuZG9tIEZvcmVzdCBjb25zaXN0cyBvZiBhbiBlbnNlbWJsZSBvZiBkZWNpc2lvbiB0cmVlcy4gSW4gdGhpcyBjYXNlLCB0aGVyZSBhcmUgMTAwIHRyZWVzIGluIHRoZSBmb3Jlc3QuIEF0IGVhY2ggbm9kZSBvZiBhIGRlY2lzaW9uIHRyZWUsIHRoZSBhbGdvcml0aG0gY29uc2lkZXJzIGEgc3Vic2V0IG9mIHByZWRpY3RvciB2YXJpYWJsZXMgZm9yIHNwbGl0dGluZy4gSGVyZSBvbmx5IDEgdmFyaWFibGUgaXMgdHJpZWQgYXQgZWFjaCBzcGxpdC4gVGhpcyBjYW4gY29udHJpYnV0ZSB0byB0aGUgZGl2ZXJzaXR5IG9mIHRoZSB0cmVlcyBpbiB0aGUgZW5zZW1ibGUuClRoZSBtZWFuIG9mIHNxdWFyZWQgcmVzaWR1YWxzIGlzIGEgbWVhc3VyZSBvZiB0aGUgYXZlcmFnZSBzcXVhcmVkIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgcHJlZGljdGVkIGFuZCBhY3R1YWwgdmFsdWVzLiBJbiB0aGlzIGNvbnRleHQsIGl0IGlzIDcwLjE4NDMyLiBBIGxvd2VyIHZhbHVlIGluZGljYXRlcyBiZXR0ZXIgbW9kZWwgZml0LCBzdWdnZXN0aW5nIHRoYXQsIG9uIGF2ZXJhZ2UsIHRoZSBwcmVkaWN0aW9ucyBhcmUgY2xvc2UgdG8gdGhlIGFjdHVhbCBsaWZlIGV4cGVjdGFuY3kgdmFsdWVzLgoKVGhlIHBlcmNlbnRhZ2Ugb2YgdmFyaWFuY2UgZXhwbGFpbmVkIGlzIGEgbWVhc3VyZSBvZiBob3cgbXVjaCB2YXJpYWJpbGl0eSBpbiB0aGUgcmVzcG9uc2UgdmFyaWFibGUgaXMgYWNjb3VudGVkIGZvciBieSB0aGUgbW9kZWwuIEluIHRoaXMgY2FzZSwgdGhlIG1vZGVsIGV4cGxhaW5zIDU2LjY4JSBvZiB0aGUgdmFyaWFuY2UgaW4gbGlmZSBleHBlY3RhbmN5LCBpbmRpY2F0aW5nIGEgbW9kZXJhdGUgbGV2ZWwgb2YgZXhwbGFuYXRvcnkgcG93ZXIuCgpPdmVyYWxsLCB0aGVzZSBtZXRyaWNzIHByb3ZpZGUgYW4gb3ZlcnZpZXcgb2YgdGhlIFJhbmRvbSBGb3Jlc3QgbW9kZWwncyBjaGFyYWN0ZXJpc3RpY3MgYW5kIHBlcmZvcm1hbmNlIG9uIHRoZSB0cmFpbmluZyBkYXRhLiBJdCBzdWdnZXN0cyB0aGF0IHRoZSBtb2RlbCBpcyBjYXB0dXJpbmcgYSBzdWJzdGFudGlhbCBwb3J0aW9uIG9mIHRoZSB2YXJpYWJpbGl0eSBpbiBsaWZlIGV4cGVjdGFuY3kgYW5kIGhhcyB0aGUgcG90ZW50aWFsIGZvciBtYWtpbmcgYWNjdXJhdGUgcHJlZGljdGlvbnMuIEhvd2V2ZXIsIHRvIGZ1bGx5IGFzc2VzcyBpdHMgcGVyZm9ybWFuY2UsIGl0J3MgZXNzZW50aWFsIHRvIGV2YWx1YXRlIHRoZSBtb2RlbCBvbiBhIHNlcGFyYXRlIHRlc3QgZGF0YXNldCB0byBlbnN1cmUgZ2VuZXJhbGl6YWJpbGl0eS4KCgojIyMgUmFuZG9tIEZvcmVzdCBTY2F0dGVyIFBsb3QgCgpUaGUgb3V0cHV0IG9mIHRoZSBSYW5kb20gRm9yZXN0IG1vZGVsIGluZGljYXRlcyBwcm9taXNpbmcgY2hhcmFjdGVyaXN0aWNzLCB3aXRoIGEgbW9kZXJhdGUgcGVyY2VudGFnZSBvZiB2YXJpYW5jZSBleHBsYWluZWQgNTYuNjglIGFuZCBhIG1lYW4gc3F1YXJlZCByZXNpZHVhbCBvZiA3MC4xODQzMi4gVG8gZnVydGhlciBhc3Nlc3MgdGhlIG1vZGVsJ3MgcHJlZGljdGl2ZSBwZXJmb3JtYW5jZSwgYSBzY2F0dGVyIHBsb3Qgb2YgYWN0dWFsIHZzIHByZWRpY3RlZCB2YWx1ZXMgaXMgY3JlYXRlZC4gVGhpcyB2aXN1YWxpemF0aW9uIGFsbG93cyBmb3IgYSBkaXJlY3QgY29tcGFyaXNvbiBiZXR3ZWVuIHRoZSBtb2RlbCdzIHByZWRpY3Rpb25zIGFuZCB0aGUgdHJ1ZS1saWZlIGV4cGVjdGFuY3kgdmFsdWVzLgoKYGBge3IsZWNobz1GQUxTRX0KCiMgQ3JlYXRlIGEgc2NhdHRlciBwbG90IG9mIGFjdHVhbCB2cy4gcHJlZGljdGVkIHZhbHVlcyBmb3IgUmFuZG9tIEZvcmVzdCBtb2RlbApnZ3Bsb3QoZGF0YSA9IHRlc3RfZGF0YSwgYWVzKHggPSBMaWZlRXhwLCB5ID0gcHJlZGljdGlvbnNfcmYpKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX2FibGluZShpbnRlcmNlcHQgPSAwLCBzbG9wZSA9IDEsIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICBsYWJzKHggPSAiQWN0dWFsIExpZmUgRXhwZWN0YW5jeSIsIHkgPSAiUHJlZGljdGVkIExpZmUgRXhwZWN0YW5jeSIsIAogICAgICAgdGl0bGUgPSAiQWN0dWFsIHZzLiBQcmVkaWN0ZWQgTGlmZSBFeHBlY3RhbmN5IChSYW5kb20gRm9yZXN0IE1vZGVsKSIpICsKICB0aGVtZV9taW5pbWFsKCkKCmBgYApUaGUgc2NhdHRlciBwbG90IHNob3djYXNlcyBpbmRpdmlkdWFsIGRhdGEgcG9pbnRzIHdoZXJlIHRoZSB4LWF4aXMgcmVwcmVzZW50cyB0aGUgYWN0dWFsIGxpZmUgZXhwZWN0YW5jeSB2YWx1ZXMsIGFuZCB0aGUgeS1heGlzIHJlcHJlc2VudHMgdGhlIGNvcnJlc3BvbmRpbmcgcHJlZGljdGVkIHZhbHVlcyBnZW5lcmF0ZWQgYnkgdGhlIFJhbmRvbSBGb3Jlc3QgbW9kZWwuIEEgcmVkIGRhc2hlZCBsaW5lIGlzIG92ZXJsYWlkIG9uIHRoZSBwbG90LCBpbmRpY2F0aW5nIHRoZSBpZGVhbCBzY2VuYXJpbyB3aGVyZSBhY3R1YWwgYW5kIHByZWRpY3RlZCB2YWx1ZXMgcGVyZmVjdGx5IGFsaWduLgoKSW4gdGhpcyBjYXNlLCB0aGUgc2NhdHRlciBwbG90IHJldmVhbHMgYSBnZW5lcmFsbHkgbGluZWFyIHBhdHRlcm4sIHN1Z2dlc3RpbmcgdGhhdCB0aGUgUmFuZG9tIEZvcmVzdCBtb2RlbCBjYXB0dXJlcyB0aGUgdW5kZXJseWluZyByZWxhdGlvbnNoaXBzIGluIHRoZSBkYXRhLiBQb2ludHMgYXJlIGNsb3NlbHkgY2x1c3RlcmVkIGFyb3VuZCB0aGUgaWRlYWwgbGluZSwgaW5kaWNhdGluZyBhIHN0cm9uZyBjb3JyZXNwb25kZW5jZSBiZXR3ZWVuIHRoZSBwcmVkaWN0ZWQgYW5kIGFjdHVhbCBsaWZlIGV4cGVjdGFuY3kgdmFsdWVzLiBUaGlzIGFsaWdubWVudCBzaWduaWZpZXMgdGhhdCB0aGUgbW9kZWwgaXMgbWFraW5nIGFjY3VyYXRlIHByZWRpY3Rpb25zLCBhbmQgdGhlIGRldmlhdGlvbnMgZnJvbSB0aGUgaWRlYWwgbGluZSBhcmUgcmVsYXRpdmVseSBzbWFsbC4KCk92ZXJhbGwsIHRoZSBzY2F0dGVyIHBsb3QgdmlzdWFsbHkgcmVpbmZvcmNlcyB0aGUgbW9kZWwncyBlZmZlY3RpdmVuZXNzLCBzaG93Y2FzaW5nIGl0cyBhYmlsaXR5IHRvIHByb3ZpZGUgcmVsaWFibGUgcHJlZGljdGlvbnMgZm9yIGxpZmUgZXhwZWN0YW5jeSBiYXNlZCBvbiBHRFAgcGVyIGNhcGl0YS4gVGhlIHByb3hpbWl0eSBvZiB0aGUgcG9pbnRzIHRvIHRoZSBpZGVhbCBsaW5lIGluZGljYXRlcyBhIHN0cm9uZyBwcmVkaWN0aXZlIHJlbGF0aW9uc2hpcCwgc3VwcG9ydGluZyB0aGUgbW9kZWwncyB1dGlsaXR5IGluIHVuZGVyc3RhbmRpbmcgYW5kIGZvcmVjYXN0aW5nIGxpZmUgZXhwZWN0YW5jeSBwYXR0ZXJucy4KCgpJIHdpbGwgbGV2ZXJhZ2UgdGhlIFN1cHBvcnQgVmVjdG9yIE1hY2hpbmUgYW5kIEdyYWRpZW50IEJvb3N0aW5nIGFsZ29yaXRobXMgdG8gY29tcGFyZSB0aGVpciBwZXJmb3JtYW5jZSB3aXRoIHRoZSBMaW5lYXIgUmVncmVzc2lvbiBhbmQgUmFuZG9tIEZvcmVzdCBtb2RlbHMuIFRoZSBvYmplY3RpdmUgaXMgdG8gZGlzY2VybiB3aGljaCBtb2RlbCB5aWVsZHMgdGhlIG1vc3QgYWNjdXJhdGUgcHJlZGljdGlvbnMgaW4gdGhlIGNvbnRleHQgb2YgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGxpZmUgZXhwZWN0YW5jeSBhbmQgR0RQIHBlciBjYXBpdGEuIEJ5IHN5c3RlbWF0aWNhbGx5IGV2YWx1YXRpbmcgdGhlc2UgZGl2ZXJzZSBhbGdvcml0aG1zLCBJIGFpbSB0byBkZXRlcm1pbmUgdGhlIG1vc3QgZWZmZWN0aXZlIGFwcHJvYWNoIGZvciBjYXB0dXJpbmcgdGhlIGludHJpY2F0ZSByZWxhdGlvbnNoaXAgYW5kIG1ha2luZyByZWxpYWJsZSBwcmVkaWN0aW9ucy4KClxuZXdwYWdlCgojIyBTdXBwb3J0IFZlY3RvciBNYWNoaW5lIFJlZ3Jlc3NvciBNb2RlbAoKQSBTdXBwb3J0IFZlY3RvciBNYWNoaW5lICBpcyBhIHN1cGVydmlzZWQgbWFjaGluZSBsZWFybmluZyBhbGdvcml0aG0gdXNlZCBmb3IgY2xhc3NpZmljYXRpb24gYW5kIHJlZ3Jlc3Npb24gdGFza3MuIFRoZSBtYWluIGlkZWEgYmVoaW5kIFNWTSBpcyB0byBmaW5kIGEgaHlwZXJwbGFuZSB0aGF0IGJlc3Qgc2VwYXJhdGVzIHRoZSBkYXRhIGludG8gZGlmZmVyZW50IGNsYXNzZXMuIFRoZSBoeXBlcnBsYW5lIGNob3NlbiBpcyB0aGUgb25lIHRoYXQgbWF4aW1pemVzIHRoZSBtYXJnaW4sIHdoaWNoIGlzIHRoZSBkaXN0YW5jZSBiZXR3ZWVuIHRoZSBoeXBlcnBsYW5lIGFuZCB0aGUgbmVhcmVzdCBkYXRhIHBvaW50IGZyb20gZWFjaCBjbGFzcyBAZW53aWtpOjExODY3ODYyODAuCgpUaGUgZXF1YXRpb24gb2YgYSBsaW5lYXIgU3VwcG9ydCBWZWN0b3IgTWFjaGluZSBpcyBhcyBmb2xsb3dzOgoKJCQKZihcbWF0aGJme3h9KSA9IFx0ZXh0e3NpZ259KFxtYXRoYmZ7d30gXGNkb3QgXG1hdGhiZnt4fSArIGIpIFxcCiQkCgokJApcYmVnaW57YWxpZ24qfQogICAgXHRleHR7V2hlcmU6fSBcXAogICAgZihcbWF0aGJme3h9KSAmIFx0ZXh0eyBpcyB0aGUgZGVjaXNpb24gZnVuY3Rpb24ufSBcXAogICAgXG1hdGhiZnt3fSAmIFx0ZXh0eyBpcyB0aGUgd2VpZ2h0IHZlY3Rvci59IFxcCiAgICBcbWF0aGJme3h9ICYgXHRleHR7IGlzIHRoZSBpbnB1dCB2ZWN0b3IufSBcXAogICAgYiAmIFx0ZXh0eyBpcyB0aGUgYmlhcyB0ZXJtLn0KXGVuZHthbGlnbip9CiQkCgokJApcdGV4dHtUaGUgb3B0aW1pemF0aW9uIHByb2JsZW0gYXNzb2NpYXRlZCB3aXRoIFNWTSBjYW4gYmUgcmVwcmVzZW50ZWQgYXMgfVxcCiQkCgokJApcdGV4dHtNaW5pbWl6ZTogfSBcZnJhY3sxfXsyfVx8XG1hdGhiZnt3fVx8XjJcXAokJAoKJCQKXHRleHR7U3ViamVjdCB0byB0aGUgY29uc3RyYWludHM6fVxcCnlfaShcbWF0aGJme3d9IFxjZG90IFxtYXRoYmZ7eH1faSArIGIpIFxnZXEgMSBcdGV4dHsgZm9yIH0gaSA9IDEsIDIsIFxsZG90cywgTgokJAogCgoKCmBgYHtyLGVjaG89RkFMU0V9CgojIExvYWQgdGhlIG5lY2Vzc2FyeSBsaWJyYXJ5CmlmICghcmVxdWlyZU5hbWVzcGFjZSgiZTEwNzEiLCBxdWlldGx5ID0gVFJVRSkpIHsKICBpbnN0YWxsLnBhY2thZ2VzKCJlMTA3MSIpCn0KIyBCdWlsZCBhIFN1cHBvcnQgVmVjdG9yIE1hY2hpbmUgUmVncmVzc29yIG1vZGVsCnN2bV9tb2RlbCA8LSBlMTA3MTo6c3ZtKExpZmVFeHAgfiBnZHBfcGVyX2NhcGl0YSwgZGF0YSA9IHRyYWluX2RhdGEpCgojIE1ha2UgcHJlZGljdGlvbnMgb24gdGhlIHRlc3Qgc2V0CnRlc3RfZGF0YSRwcmVkaWN0aW9uc19zdm0gPC0gcHJlZGljdChzdm1fbW9kZWwsIG5ld2RhdGEgPSB0ZXN0X2RhdGEpCgojIENhbGN1bGF0ZSBSLXNxdWFyZWQgc2NvcmUgZm9yIFNWTQpzdm1fcl9zcXVhcmVkIDwtIDEgLSBzdW0oKHRlc3RfZGF0YSRMaWZlRXhwIC0gdGVzdF9kYXRhJHByZWRpY3Rpb25zX3N2bSleMikgLyBzdW0oKHRlc3RfZGF0YSRMaWZlRXhwIC0gbWVhbih0ZXN0X2RhdGEkTGlmZUV4cCkpXjIpCgpwcmludChwYXN0ZSgiU1ZNIFItc3F1YXJlZCBTY29yZTogIiwgcm91bmQoc3ZtX3Jfc3F1YXJlZCwgMikpKQoKIyBCdWlsZCBhIFN1cHBvcnQgVmVjdG9yIE1hY2hpbmUgUmVncmVzc29yIG1vZGVsCiNzdm1fbW9kZWwgPC0gc3ZtKExpZmVFeHAgfiBnZHBfcGVyX2NhcGl0YSwgZGF0YSA9IHRyYWluX2RhdGEpCgojIE1ha2UgcHJlZGljdGlvbnMgb24gdGhlIHRlc3Qgc2V0CiN0ZXN0X2RhdGEkcHJlZGljdGlvbnNfc3ZtIDwtIHByZWRpY3Qoc3ZtX21vZGVsLCBuZXdkYXRhID0gdGVzdF9kYXRhKQoKIyBDYWxjdWxhdGUgUi1zcXVhcmVkIHNjb3JlIGZvciBTVk0KI3N2bV9yX3NxdWFyZWQgPC0gMSAtIHN1bSgodGVzdF9kYXRhJExpZmVFeHAgLSB0ZXN0X2RhdGEkcHJlZGljdGlvbnNfc3ZtKV4yKSAvIHN1bSgodGVzdF9kYXRhJExpZmVFeHAgLSAjbWVhbih0ZXN0X2RhdGEkTGlmZUV4cCkpXjIpCgojcHJpbnQocGFzdGUoIlNWTSBSLXNxdWFyZWQgU2NvcmU6ICIsIHJvdW5kKHN2bV9yX3NxdWFyZWQsIDIpKSkKCmBgYAoKIyMgR3JhZGllbnQgQm9vc3RpbmcgUmVncmVzc29yIE1vZGVsCgpHcmFkaWVudCBCb29zdGluZyBpcyBhbiBlbnNlbWJsZSBsZWFybmluZyB0ZWNobmlxdWUgdXNlZCBmb3IgYm90aCByZWdyZXNzaW9uIGFuZCBjbGFzc2lmaWNhdGlvbiB0YXNrcy4gVGhlIGFsZ29yaXRobSBidWlsZHMgYSBzZXJpZXMgb2Ygd2VhayBsZWFybmVycywgdHlwaWNhbGx5IGRlY2lzaW9uIHRyZWVzLCBhbmQgY29tYmluZXMgdGhlbSB0byBjcmVhdGUgYSBzdHJvbmcgbGVhcm5lci4gR3JhZGllbnQgQm9vc3RpbmcgZm9jdXNlcyBvbiBtaW5pbWl6aW5nIHRoZSBlcnJvcnMgb2YgdGhlIHByZXZpb3VzIG1vZGVscyBieSBhZGRpbmcgbmV3IG1vZGVscyB0aGF0IGNvcnJlY3QgdGhlIG1pc3Rha2VzIG9mIHRoZSBleGlzdGluZyBvbmVzIEBlbndpa2k6MTE3NzI1ODkxMy4KCiQkCkZfbSh4KSA9IEZfe20tMX0oeCkgKyBcbnUgaF9tKHgpCiQkCgokJApcdGV4dHt3aGVyZTp9IFxcCiAgICBGX20oeCkgXHRleHR7IGlzIHRoZSBtb2RlbCBhdCBpdGVyYXRpb24gfSBtIFxcCiAgICBGX3ttLTF9KHgpIFx0ZXh0eyBpcyB0aGUgbW9kZWwgZnJvbSB0aGUgcHJldmlvdXMgaXRlcmF0aW9ufSBcXAogICAgXG51IFx0ZXh0eyBpcyB0aGUgbGVhcm5pbmcgcmF0ZSwgYSBoeXBlcnBhcmFtZXRlciBpbiB0aGUgcmFuZ2UgKDAsIDEpfSBcXAogICAgaF9tKHgpIFx0ZXh0eyBpcyB0aGUgd2VhayBsZWFybmVyIChlLmcuLCBhIGRlY2lzaW9uIHRyZWUpIHRyYWluZWQgdG8gY29ycmVjdCB0aGUgcmVzaWR1YWxzfSBcXAokJAoKCmBgYHtyLGVjaG89RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQoKIyBMb2FkIHRoZSBuZWNlc3NhcnkgbGlicmFyeQppbnN0YWxsLnBhY2thZ2VzKCJnYm0iKQpsaWJyYXJ5KGdibSkKCiMgQnVpbGQgYSBHcmFkaWVudCBCb29zdGluZyBSZWdyZXNzb3IgbW9kZWwKZ2JtX21vZGVsIDwtIGdibShMaWZlRXhwIH4gZ2RwX3Blcl9jYXBpdGEsIGRhdGEgPSB0cmFpbl9kYXRhLCBuLnRyZWVzID0gMTAwLCBpbnRlcmFjdGlvbi5kZXB0aCA9IDMpCgojIE1ha2UgcHJlZGljdGlvbnMgb24gdGhlIHRlc3Qgc2V0CnRlc3RfZGF0YSRwcmVkaWN0aW9uc19nYm0gPC0gcHJlZGljdChnYm1fbW9kZWwsIG5ld2RhdGEgPSB0ZXN0X2RhdGEsIG4udHJlZXMgPSAxMDApCgojIENhbGN1bGF0ZSBSLXNxdWFyZWQgc2NvcmUgZm9yIEdyYWRpZW50IEJvb3N0aW5nCmdibV9yX3NxdWFyZWQgPC0gMSAtIHN1bSgodGVzdF9kYXRhJExpZmVFeHAgLSB0ZXN0X2RhdGEkcHJlZGljdGlvbnNfZ2JtKV4yKSAvIHN1bSgodGVzdF9kYXRhJExpZmVFeHAgLSBtZWFuKHRlc3RfZGF0YSRMaWZlRXhwKSleMikKCnByaW50KHBhc3RlKCJHcmFkaWVudCBCb29zdGluZyBSLXNxdWFyZWQgU2NvcmU6ICIsIHJvdW5kKGdibV9yX3NxdWFyZWQsIDIpKSkKCmBgYApcbmV3cGFnZQoKIyBNb2RlbCBFdmFsdWF0aW9uIAoKYGBge3IsZWNobz1GQUxTRSxyZXN1bHRzPSdoaWRlJ30KIyBDYWxjdWxhdGUgUk1TRSBmb3IgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwKbG1fcm1zZSA8LSBzcXJ0KG1lYW4oKHRlc3RfZGF0YSRMaWZlRXhwIC0gcHJlZGljdChsbV9tb2RlbCwgbmV3ZGF0YSA9IHRlc3RfZGF0YSkpXjIpKQoKIyBDYWxjdWxhdGUgUk1TRSBmb3IgUmFuZG9tIEZvcmVzdApyZl9ybXNlIDwtIHNxcnQobWVhbigodGVzdF9kYXRhJExpZmVFeHAgLSB0ZXN0X2RhdGEkcHJlZGljdGlvbnNfcmYpXjIpKQoKIyBDYWxjdWxhdGUgUk1TRSBmb3IgR3JhZGllbnQgQm9vc3RpbmcKZ2JtX3Jtc2UgPC0gc3FydChtZWFuKCh0ZXN0X2RhdGEkTGlmZUV4cCAtIHRlc3RfZGF0YSRwcmVkaWN0aW9uc19nYm0pXjIpKQoKIyBDYWxjdWxhdGUgUk1TRSBmb3IgU1ZNCnN2bV9ybXNlIDwtIHNxcnQobWVhbigodGVzdF9kYXRhJExpZmVFeHAgLSB0ZXN0X2RhdGEkcHJlZGljdGlvbnNfc3ZtKV4yKSkKCiMgUHJpbnQgUk1TRSB2YWx1ZXMKcHJpbnQocGFzdGUoIkxpbmVhciBSZWdyZXNzaW9uIFJNU0U6ICIsIHJvdW5kKGxtX3Jtc2UsIDIpKSkKcHJpbnQocGFzdGUoIlJhbmRvbSBGb3Jlc3QgUk1TRTogIiwgcm91bmQocmZfcm1zZSwgMikpKQpwcmludChwYXN0ZSgiR3JhZGllbnQgQm9vc3RpbmcgUk1TRTogIiwgcm91bmQoZ2JtX3Jtc2UsIDIpKSkKcHJpbnQocGFzdGUoIlNWTSBSTVNFOiAiLCByb3VuZChzdm1fcm1zZSwgMikpKQoKYGBgCgojIyBSTVNFIENvbXBhcmlzb24gb2YgUmVncmVzc2lvbiBNb2RlbHMKClJvb3QgTWVhbiBTcXVhcmVkIEVycm9yIGlzIGEgbWV0cmljIHVzZWQgdG8gZXZhbHVhdGUgdGhlIGFjY3VyYWN5IG9mIGEgcmVncmVzc2lvbiBtb2RlbCwgaXQgcHJvdmlkZXMgYSBtZWFzdXJlIG9mIGhvdyB3ZWxsIHRoZSBtb2RlbCdzIHByZWRpY3Rpb25zIG1hdGNoIHRoZSBhY3R1YWwgb2JzZXJ2ZWQgdmFsdWVzLiBSTVNFIG1lYXN1cmVzIHRoZSBhdmVyYWdlIG1hZ25pdHVkZSBvZiB0aGUgZXJyb3JzIGJldHdlZW4gcHJlZGljdGVkIGFuZCBhY3R1YWwgdmFsdWVzIGFuZCBpdCBwZW5hbGl6ZXMgbGFyZ2VyIGVycm9ycyBtb3JlIGhlYXZpbHkgdGhhbiBzbWFsbGVyIG9uZXMuCmBgYHtyLGVjaG89RkFMU0V9CgojIENyZWF0ZSBhIGJhciBjaGFydCB0byBjb21wYXJlIFJNU0UgdmFsdWVzCm1vZGVsX25hbWVzIDwtIGMoIkxpbmVhciBSZWdyZXNzaW9uIiwgIlJhbmRvbSBGb3Jlc3QiLCAiR3JhZGllbnQgQm9vc3RpbmciLCAiU1ZNIikKcm1zZV92YWx1ZXMgPC0gYyhsbV9ybXNlLCByZl9ybXNlLCBnYm1fcm1zZSwgc3ZtX3Jtc2UpCgpiYXJwbG90KHJtc2VfdmFsdWVzLCBuYW1lcy5hcmcgPSBtb2RlbF9uYW1lcywgY29sID0gInNreWJsdWUiLCAKICAgICAgICBtYWluID0gIlJNU0UgQ29tcGFyaXNvbiBvZiBSZWdyZXNzaW9uIE1vZGVscyIsCiAgICAgICAgeWxhYiA9ICJSb290IE1lYW4gU3F1YXJlZCBFcnJvciAoUk1TRSkiLCB5bGltID0gYygwLCBtYXgocm1zZV92YWx1ZXMpICsgNSkpCgpgYGAKVXN1YWxseSwgYSBsb3dlciBSTVNFIHZhbHVlIGluZGljYXRlcyBiZXR0ZXIgbW9kZWwgcGVyZm9ybWFuY2UsIGFzIGl0IG1lYW5zIHRoZSBtb2RlbCdzIHByZWRpY3Rpb25zIGFyZSBjbG9zZXIgdG8gdGhlIGFjdHVhbCB2YWx1ZXMuIFRoZXJlZm9yZSwgYmFzZWQgb24gdGhlIGFib3ZlIHJlc3VsdHMsIHRoZSBHcmFkaWVudCBCb29zdGluZyBtb2RlbCBzZWVtcyB0byBwZXJmb3JtIHRoZSBiZXN0IGFtb25nIHRoZSBtb2RlbHMsIGZvbGxvd2VkIGNsb3NlbHkgYnkgdGhlIFNWTSBtb2RlbCwgdGhlbiB0aGUgUmFuZG9tIEZvcmVzdCwgYW5kIGZpbmFsbHkgTGluZWFyIFJlZ3Jlc3Npb24uCmBgYHtyLGVjaG89RkFMU0UscmVzdWx0cz0naGlkZSd9CnIyX2xtIDwtIDEgLSAoc3VtKCh0ZXN0X2RhdGEkTGlmZUV4cCAtIHRlc3RfZGF0YSRwcmVkaWN0aW9ucyleMikgLyBzdW0oKHRlc3RfZGF0YSRMaWZlRXhwIC0gbWVhbih0ZXN0X2RhdGEkTGlmZUV4cCkpXjIpKQpyMl9yZiA8LSAxIC0gKHN1bSgodGVzdF9kYXRhJExpZmVFeHAgLSB0ZXN0X2RhdGEkcHJlZGljdGlvbnNfcmYpXjIpIC8gc3VtKCh0ZXN0X2RhdGEkTGlmZUV4cCAtIG1lYW4odGVzdF9kYXRhJExpZmVFeHApKV4yKSkKcjJfZ2JtIDwtIDEgLSAoc3VtKCh0ZXN0X2RhdGEkTGlmZUV4cCAtIHRlc3RfZGF0YSRwcmVkaWN0aW9ucyleMikgLyBzdW0oKHRlc3RfZGF0YSRMaWZlRXhwIC0gbWVhbih0ZXN0X2RhdGEkTGlmZUV4cCkpXjIpKQpyMl9zdm0gPC0gMSAtIChzdW0oKHRlc3RfZGF0YSRMaWZlRXhwIC0gdGVzdF9kYXRhJHByZWRpY3Rpb25zX3JmKV4yKSAvIHN1bSgodGVzdF9kYXRhJExpZmVFeHAgLSBtZWFuKHRlc3RfZGF0YSRMaWZlRXhwKSleMikpCgoKYGBgClxuZXdwYWdlCgojIyBSLVNxdWFyZWQgQ29tcGFyaXNvbiBvZiBSZWdyZXNzaW9uIE1vZGVscwoKVGhlIFItc3F1YXJlZCBpcyBhIHN0YXRpc3RpY2FsIG1lYXN1cmUgb2YgaG93IHdlbGwgdGhlIGluZGVwZW5kZW50IHZhcmlhYmxlcyBpbiBhIHJlZ3Jlc3Npb24gbW9kZWwgZXhwbGFpbiB0aGUgdmFyaWFiaWxpdHkgb2YgdGhlIGRlcGVuZGVudCB2YXJpYWJsZS4gSXQgaXMgYSBzY2FsZSBmcm9tIDAgdG8gMS4gd2hlcmU6CjAgaW5kaWNhdGVzIHRoYXQgdGhlIG1vZGVsIGRvZXMgbm90IGV4cGxhaW4gYW55IG9mIHRoZSB2YXJpYWJpbGl0eSBpbiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlLgoxIGluZGljYXRlcyB0aGF0IHRoZSBtb2RlbCBleHBsYWlucyBhbGwgb2YgdGhlIHZhcmlhYmlsaXR5IGluIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUuCmBgYHtyLCBlY2hvPUZBTFNFfQojIENyZWF0ZSBhIGJhciBjaGFydCB0byBjb21wYXJlIFItc3F1YXJlZCB2YWx1ZXMKbW9kZWxfbmFtZXMgPC0gYygiTGluZWFyIFJlZ3Jlc3Npb24iLCAiUmFuZG9tIEZvcmVzdCIsICJHcmFkaWVudCBCb29zdGluZyIsICJTVk0iKQpyX3NxdWFyZWRfdmFsdWVzIDwtIGMobG1fcl9zcXVhcmVkLCByZl9yX3NxdWFyZWQsIGdibV9yX3NxdWFyZWQsIHN2bV9yX3NxdWFyZWQpCgpiYXJwbG90KHJfc3F1YXJlZF92YWx1ZXMsIG5hbWVzLmFyZyA9IG1vZGVsX25hbWVzLCBjb2wgPSAibGlnaHRncmVlbiIsIAogICAgICAgIG1haW4gPSAiUi1TcXVhcmVkIENvbXBhcmlzb24gb2YgUmVncmVzc2lvbiBNb2RlbHMiLAogICAgICAgIHlsYWIgPSAiUi1TcXVhcmVkIiwgeWxpbSA9IGMoMCwgbWF4KHJfc3F1YXJlZF92YWx1ZXMpICsgMC4yKSkKCiMgQWRkIHZhbHVlcyBvbiB0b3Agb2YgdGhlIGJhcnMKdGV4dCgxOjQsIHJfc3F1YXJlZF92YWx1ZXMgKyAwLjA1LCByb3VuZChyX3NxdWFyZWRfdmFsdWVzLCAyKSwgcG9zID0gMywgY2V4ID0gMS4zLCBjb2wgPSAiYmxhY2siKQoKYGBgIApSLXNxdWFyZWQgdmFsdWUgb2YgMC42OCBpbmRpY2F0ZXMgdGhhdCB0aGUgR3JhZGllbnQgQm9vc3RpbmcgbW9kZWwgaXMgcmVhc29uYWJseSBlZmZlY3RpdmUgYXQgZXhwbGFpbmluZyB0aGUgdmFyaWF0aW9uIGluIHRoZSB0YXJnZXQgdmFyaWFibGUuIEhvd2V2ZXIsIGl0J3MgY3J1Y2lhbCB0byBjb25zaWRlciBvdGhlciBhc3BlY3RzIG9mIG1vZGVsIGV2YWx1YXRpb24gYW5kIHRoZSBzcGVjaWZpYyBnb2FscyBvZiB0aGlzIHByb2plY3QuIAoKIyBMaW1pdGF0aW9ucyAKVGhlIHByb2plY3QgcmVsaWVzIG9uIGF2YWlsYWJsZSBkYXRhLCBhbmQgYW55IGdhcHMgb3IgaW5hY2N1cmFjaWVzIGluIHRoZSBkYXRhIGNvdWxkIGltcGFjdCB0aGUgcmVzdWx0cy4gVGhlIG1vZGVscyB1c2VkIG1ha2UgY2VydGFpbiBhc3N1bXB0aW9ucywgYW5kIHRoZSByZWFsLXdvcmxkIHJlbGF0aW9uc2hpcCBpcyBsaWtlbHkgaW5mbHVlbmNlZCBieSBudW1lcm91cyBjb21wbGV4IGZhY3RvcnMuIFdoaWxlIHRoZSBwcm9qZWN0IGV4cGxvcmVzIGNvcnJlbGF0aW9ucywgZXN0YWJsaXNoaW5nIGNhdXNhdGlvbiByZXF1aXJlcyBtb3JlIGluLWRlcHRoIHN0dWRpZXMgYW5kIGNvbnNpZGVyYXRpb25zIG9mIGNvbmZvdW5kaW5nIHZhcmlhYmxlcy4KCiMgRnVydGhlciBBbmFseXNpcyBBcmVhcwpUbyBjb25kdWN0IGEgbW9yZSBleHRlbnNpdmUgYW5hbHlzaXMsIHNvbWVvbmUgY2FuIGV4cGxvcmUgaG93IHRoZSByZWxhdGlvbnNoaXAgZXZvbHZlcyBvdmVyIHRpbWUgYnkgaW5jb3Jwb3JhdGluZyBkYXRhIGZyb20gYWRkaXRpb25hbCB5ZWFycy4gRm9yIGEgZGV0YWlsZWQgcmVnaW9uYWwgYW5hbHlzaXMsIGl0IHdvdWxkIGJlIGJlbmVmaWNpYWwgdG8gY29uZHVjdCBhIG1vcmUgZ3JhbnVsYXIgZXhhbWluYXRpb24gb2Ygc3BlY2lmaWMgcmVnaW9ucywgaW4gb3JkZXIgIHRvIHVuY292ZXIgcmVnaW9uYWwgdmFyaWF0aW9ucyBhbmQgdHJlbmRzLiBBZGRpdGlvbmFsbHksIGludmVzdGlnYXRpbmcgc3VwcGxlbWVudGFyeSBmYWN0b3JzIHN1Y2ggYXMgaGVhbHRoY2FyZSBpbmZyYXN0cnVjdHVyZSwgZWR1Y2F0aW9uLCBhbmQgc29jaWFsIHBvbGljaWVzIGNvdWxkIHByb3ZpZGUgaW5zaWdodHMgaW50byB0aGVpciBjb250cmlidXRpb25zIHRvIGxpZmUgZXhwZWN0YW5jeS4KCiMgQ29uY2x1c2lvbnMKVGhpcyBwcm9qZWN0IGhhcyB1bmRlcnRha2VuIGEgdGhvcm91Z2ggaW52ZXN0aWdhdGlvbiBpbnRvIHRoZSBjb21wbGV4IGludGVycGxheSBiZXR3ZWVuIGxpZmUgZXhwZWN0YW5jeSBhbmQgR0RQIHBlciBjYXBpdGEsIGxldmVyYWdpbmcgYSBkaXZlcnNlIHNldCBvZiBtYWNoaW5lIGxlYXJuaW5nIG1vZGVscyBhbmQgYWxnb3JpdGhtcy4gVGhlIGFuYWx5c2lzIHVuZWFydGhlZCBpbnRyaWNhdGUgcGF0dGVybnMgYW5kIGNvbXBsZXhpdGllcyBpbiB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlc2UgdmFyaWFibGVzLiBOb3RhYmx5LCBvdXIga2V5IGZpbmRpbmdzIGlsbHVtaW5hdGUgdGhlIGxvZ2FyaXRobWljIG5hdHVyZSBvZiB0aGlzIHJlbGF0aW9uc2hpcCwgcmV2ZWFsaW5nIHRoYXQgdGhlIGluZmx1ZW5jZSBvZiBHRFAgcGVyIGNhcGl0YSBvbiBsaWZlIGV4cGVjdGFuY3kgZXhoaWJpdHMgdmFyaWF0aW9ucyBhY3Jvc3MgZGlmZmVyZW50IGVjb25vbWljIGNvbnRleHRzLgoKVGhlIHJlc3VsdHMgb2YgdGhpcyBwcm9qZWN0IHByb3ZpZGUgdmFsdWFibGUgaW5zaWdodHMgaW50byB1bmRlcnN0YW5kaW5nIGhvdyBlY29ub21pYyBwcm9zcGVyaXR5IGFuZCBsaWZlIGV4cGVjdGFuY3kgYXJlIGxpbmtlZCBnbG9iYWxseS4gQnkgYWNrbm93bGVkZ2luZyBhbmQgZW1icmFjaW5nIHRoZSBzdWJ0bGUgY29tcGxleGl0aWVzIGluIHRoZXNlIGNvbm5lY3Rpb25zLCBteSByZXNlYXJjaCBsYXlzIHRoZSBncm91bmR3b3JrIGZvciBtb3JlIGluZm9ybWVkIGFuZCB0YWlsb3JlZCBzdHJhdGVnaWVzLiBGdXJ0aGVyIGFuYWx5c2VzIGFuZCBjYXJlZnVsIGNvbnNpZGVyYXRpb25zIHdpbGwgdW5kb3VidGVkbHkgcmVmaW5lIG91ciB1bmRlcnN0YW5kaW5nLCBndWlkaW5nIHRoZSBkZXZlbG9wbWVudCBvZiBjb21wcmVoZW5zaXZlIGFwcHJvYWNoZXMgdG8gdGFja2xlIHVyZ2VudCBjaGFsbGVuZ2VzIGluIHB1YmxpYyBoZWFsdGggYW5kIHNvY2lvLWVjb25vbWljIGRvbWFpbnMuCgoKCgoKXG5ld3BhZ2UKCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjEwMCUifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiL1VzZXJzL3NoYW1pbWEvRGVza3RvcC9Qcm9qZWN0XzEvaW1hZ2VzL0Y0RkxvZ28ucG5nIiwgZXJyb3IgPSBGQUxTRSkKCmBgYAoKIyAqKkZvcmVjYXN0aW5nIG9mIFBldCBGb29kcyBEZW1hbmQgIFVzaW5nIFRpbWUgU2VyaWVzIEFuYWx5c2lzIHRvIEVuaGFuY2UgU3RyYXRlZ2ljIFRlY2huaXF1ZXMgYW5kIFJlc291cmNlIEFsbG9jYXRpb24gZm9yIGEgTm9uLXByb2ZpdCBPcmdhbml6YXRpb24qKgoKCgoKIyBCYWNrZ3JvdW5kCgpGcmllbmRzIGZvciBMaWZlIGlzIGEgSG91c3Rvbi1iYXNlZCBub25wcm9maXQgb3JnYW5pemF0aW9uIHRoYXQgcHJvdmlkZXMgc2VydmljZXMgdG8gcGV0IG93bmVycyBpbiBuZWVkIHRocm91Z2hvdXQgdGhlIEdyZWF0ZXIgSG91c3RvbiBjb21tdW5pdHkuICBGb3VuZGVkIGluIDIwMDEsIEZyaWVuZHMgZm9yIExpZmUgaGFzIGJlZW4gYSBkZWRpY2F0ZWQgZm9yY2UgaW4gc2VydmluZyBwZXRzIGFjcm9zcyBHcmVhdGVyIEhvdXN0b24uIEluaXRpYWxseSBjb25jZWl2ZWQgYXMgYW4gYW5pbWFsIHNoZWx0ZXIsIHRoZSBvcmdhbml6YXRpb24ncyBwcmltYXJ5IGNvbW1pdG1lbnQgbGllcyBpbiBlbnN1cmluZyB0aGUgc2FmZXR5IGFuZCB3ZWxsLWJlaW5nIG9mIGFuaW1hbHMsIGZvc3RlcmluZyBlbmR1cmluZyBjb25uZWN0aW9ucyB3aXRoIHRoZSBodW1hbnMgd2hvIGNoZXJpc2ggdGhlbS4gQmV5b25kIGVzdGFibGlzaGluZyB0aGUgY2l0eSdzIGZpcnN0IG5vLWtpbGwgc2hlbHRlciwgRnJpZW5kcyBmb3IgTGlmZSBhY3RpdmVseSBlbmdhZ2VzIGluIHBldCBhZG9wdGlvbiBpbml0aWF0aXZlcyBhbmQgcHJvdmlkZXMgZXNzZW50aWFsIG1lZGljYWwgc3VwcG9ydCBmb3IgYW5pbWFscy4KCkRyaXZlbiBieSBhIHBhc3Npb24gZm9yIGluc3RpZ2F0aW5nIHN5c3RlbWljIGNoYW5nZSBmb3IgdGhlIGJldHRlcm1lbnQgb2YgYW5pbWFsIGxpdmVzLCB0aGUgb3JnYW5pemF0aW9uIGhhcyBldm9sdmVkIHRvIGFkZHJlc3MgdmFyaW91cyBmYWNldHMgb2YgcGV0IHdlbGZhcmUuIEluIHJlY29nbml0aW9uIG9mIHRoZSB3aWRlc3ByZWFkIGltcGFjdCBvZiBmb29kIGluc2VjdXJpdHksIEZyaWVuZHMgZm9yIExpZmUgaGFzIHRob3VnaHRmdWxseSBpbnRyb2R1Y2VkIGEgcGV0IGZvb2QgYmFuayBmb3IgcGV0IG93bmVycyBmYWNpbmcgZWNvbm9taWMgY2hhbGxlbmdlcy4gRXZlcnkgeWVhciwgdGhleSBnZW5lcm91c2x5IGRpc3RyaWJ1dGUgc3Vic3RhbnRpYWwgYW1vdW50cyBvZiBwZXQgZm9vZCwgbWFraW5nIGEgdGFuZ2libGUgZGlmZmVyZW5jZSBpbiB0aGUgbGl2ZXMgb2YgcGV0cyBhbmQgdGhlaXIgb3duZXJzLiBUaGlzIHByb2plY3QgZGVsdmVzIGludG8gdGhlIGhlYXJ0IG9mIHRoZWlyIGltcGFjdGZ1bCB3b3JrIGluIHRoZSByZWFsbSBvZiBwZXQgZm9vZCBkaXN0cmlidXRpb24uCgpUaGUgb3JnYW5pemF0aW9uIHJlY29nbml6ZXMgdGhhdCB0aGVpciBjdXJyZW50IGhlYWRxdWFydGVycyBsb2NhdGlvbiBkb2VzIG5vdCBuZWNlc3NhcmlseSByZWZsZWN0IHRoZSBsb3dlciBzb2Npb2Vjb25vbWljIGFyZWFzIHdoZXJlIHRoZXJlIGlzIGEgZ3JlYXRlciBuZWVkIGZvciB0aGVpciBwZXQgZm9vZCBzZXJ2aWNlcy4gVGhleSB3YW50IHRvIGxldmVyYWdlIGludGVybmFsIGRhdGEgdG8gaGVscCB1bmNvdmVyIGRpc2NyZXBhbmNpZXMgaW4gaGlnaGVyIG5lZWQgY29tbXVuaXRpZXMgYW5kIGV4cGFuZCB0aGVpciBvdXRyZWFjaC4gT3ZlciB0aGUgeWVhcnMsIEZyaWVuZHMgZm9yIExpZmUgaGFzIGNvbGxlY3RlZCBkYXRhIG9uIHRoZWlyIHBldCBmb29kIGJhbmsgdXNhZ2UgYW5kIGludmVudG9yeS4gSG93ZXZlciwgdGhlIGRhdGEgaGF2ZSBub3QgYmVlbiBhc3NlbWJsZWQsIGNsZWFuZWQsIGV4dHJhY3RlZCwgYW5kIGFuYWx5emVkIHRvIHRoZWlyIGZ1bGwgcG90ZW50aWFsLiBbaGVyZSBpcyB0aGUgd2Vic2l0ZSBvZiB0aGUgb3JnYW5pemF0aW9uXSAoaHR0cHM6Ly9mcmllbmRzNGxpZmUub3JnKQoKVGhlIG1haW4gb2JqZWN0aXZlIG9mIHRoaXMgcHJvamVjdCBpcyB0byBwcm92aWRlIHRlY2huaWNhbCBtZWFucyBmb3IgRnJpZW5kcyBmb3IgTGlmZSB0byBlZmZpY2llbnRseSBsZXZlcmFnZSBhbmQgdW5kZXJzdGFuZCBkYXRhIHRoYXQgYXJlIGNyaXRpY2FsIHRvIGl0cyBmdXR1cmUgZnVuZHJhaXNpbmcgYW5kIG91dHJlYWNoIGVmZm9ydHMuIFRoaXMgaW5jbHVkZXM6W1ByZXZpb3VzIFByb2plY3QgTGlua10oaHR0cHM6Ly9kcml2ZS5nb29nbGUuY29tL2RyaXZlL2ZvbGRlcnMvMXNrTEVTRHdaN0o1QjItWnVKTGF2bGNRSXRrOUdiUVdQKSAKCiogRGV2ZWxvcCBhIGNlbnRyYWwgZGFzaGJvYXJkIHRoYXQgd2lsbCBjYXB0dXJlLCBhZ2dyZWdhdGUsIGFuYWx5emUsIHZpc3VhbGl6ZSwgYW5kIGZvcmVjYXN0IGRhdGEgdGhhdCB0aGUgbm9ucHJvZml0IGNhbiBpZGVudGlmeSBib3RoIHRoZWlyIGhpc3RvcmljYWwgZGlzdHJpYnV0aW9uLCBpbmNyZWFzZSBvdXRyZWFjaCBpbiBoaWdoLW5lZWQgY29tbXVuaXRpZXMgYW5kIGxldmVyYWdlIHRvIGRpcmVjdGx5IHN1cHBvcnQgZnVuZHJhaXNpbmcuCgoqCVRoZSBhcHBsaWNhdGlvbiBvZiB0aW1lIHNlcmllcyBhbmFseXNpcyB0ZWNobmlxdWVzIGZhY2lsaXRhdGVzIHRoZSBhY2N1cmF0ZSBmb3JlY2FzdGluZyBvZiBtb250aGx5IGRlbWFuZCBmb3IgYm90aCBEcnkgRm9vZHMgYW5kIFdldCBGb29kcywgcHJvdmlkaW5nIHRoZSBvcmdhbml6YXRpb24gd2l0aCB2YWx1YWJsZSBpbnNpZ2h0cyB0byBlbmhhbmNlIHRoZSBlZmZpY2llbmN5IG9mIG1hbmFnaW5nIGl0cyBwZXQgZm9vZCBiYW5rLgoKKglJbnRlZ3JhdGlvbiBvZiBkYXRhIGludG8gYSBNeVNRTCBkYXRhYmFzZSwgY29tcGxlbWVudGVkIGJ5IHByZWNpc2UgcXVlcmllcywgZW5oYW5jZXMgdGhlIGNhcGFiaWxpdHkgZm9yIGluZm9ybWVkIGRlY2lzaW9uLW1ha2luZyBpbiBzdHJhdGVnaWMgcGxhbnMgYW5kIG9wdGltaXppbmcgcmVzb3VyY2UgYWxsb2NhdGlvbi4KClRoZSBwdXJwb3NlIG9mIHRoaXMgcHJvamVjdCBpcyB0bzogCgoqIEVmZmljaWVudGx5IHByb2Nlc3MgaW5zaWdodHMgZnJvbSBwZXQgZm9vZCBiYW5rIGRhdGEKCioJQWdncmVnYXRlLCB2aXN1YWxpemUsICYgZW5hYmxlIGRhdGEgZm9yZWNhc3RpbmcgdG8gc3VwcG9ydCBwbGFubmluZyAmIGZ1bmRpbmcKCioJTG9jYXRlIGhpZ2gtbmVlZCBjb21tdW5pdGllcyB0byBkaXJlY3QgdGhlaXIgb3V0cmVhY2gKCioJSWRlbnRpZnkgMy01IHVuZGVyc2VydmVkIHppcCBjb2RlIGFyZWFzIHdpdGggaGlnaCBwZXQgZm9vZCBuZWVkcwoKKglTdXBwb3J0IGZ1dHVyZSBpbnZlbnRvcnksIGNhbXBhaWduIHBsYW5uaW5nICYgZnVuZHJhaXNpbmcuCgojIERhdGEKCkhhbmRsaW5nIHRoZSBkYXRhIHBvc2VkIGEgc2lnbmlmaWNhbnQgY2hhbGxlbmdlLiBVcG9uIHJlY2VpdmluZyB0aGUgRnJpZW5kcyBmb3IgTGlmZSBkYXRhc2V0LCB3ZSBmYWNlZCB2YXJpb3VzIGlzc3VlcywgaW5jbHVkaW5nIGluY29ycmVjdCBhbmQgbWlzc2luZyB6aXAgY29kZXMgaW4gdGhlIGFkZHJlc3NlcywgdW5jbGVhciBwZXQgdHlwZSBlbnRyaWVzLCBhbmQgbnVtZXJvdXMgY2VsbHMgcmVxdWlyaW5nIGNsZWFuaW5nLiBBZGRyZXNzaW5nIHRoZXNlIGlzc3VlcyByZXF1aXJlZCBjb25zaWRlcmFibGUgZWZmb3J0LCBlc3BlY2lhbGx5IGluIGNvcnJlY3RpbmcgemlwIGNvZGVzIGZvciBlYWNoIGFkZHJlc3MuIFRoaXMgcHJvY2VzcyBpbnZvbHZlZCB0aG9yb3VnaCB2ZXJpZmljYXRpb24gdG8gZ3VhcmFudGVlIGRhdGEgYWNjdXJhY3ksIHN1YnN0YW50aWFsbHkgYWRkaW5nIHRvIHRoZSB0aW1lIGRlZGljYXRlZCB0byBkYXRhIGNsZWFuaW5nIGFuZCB2YWxpZGF0aW9uLiBUaGUgZm9sbG93aW5nIHR3byBmaWd1cmVzIGlsbHVzdHJhdGluZyBpbnN0YW5jZXMgb2YgbWlzc2luZyBhbmQgaW5jb3JyZWN0IHppcCBjb2RlcywgYWxvbmcgd2l0aCB0aGUgbWV0aG9kIHVzZWQgdG8gcmVjdGlmeSBhbWJpZ3VvdXMgcGV0IHR5cGUgZW50cmllcy4KCmBgYHtyLCBlY2hvPUZBTFNFLGZpZy53aWR0aD03LGZpZy5oZWlnaHQ9Mywgb3V0LndpZHRoPSI1MCUifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiL1VzZXJzL3NoYW1pbWEvRGVza3RvcC9Qcm9qZWN0XzEvaW1hZ2VzL0RhdGEyLnBuZyIsIGVycm9yID0gRkFMU0UpCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIvVXNlcnMvc2hhbWltYS9EZXNrdG9wL1Byb2plY3RfMS9pbWFnZXMvRGF0YTEucG5nIiwgZXJyb3IgPSBGQUxTRSkKCmBgYAoKCkZyb20gdGhlIGRhdGEgcHJlc2VudGVkIGFib3ZlLCBpdCdzIGFwcGFyZW50IHRoYXQgdGhlcmUgaXMgYSBtaXNtYXRjaCBiZXR3ZWVuIGFkZHJlc3NlcyBhbmQgemlwIGNvZGVzIGluIHRoZSBvcmFuZ2UtY29sb3JlZCBjZWxscywgZXZlbiB0aG91Z2ggdGhlIHN0cmVldCBhZGRyZXNzZXMgYXJlIHRoZSBzYW1lLlRoZSBjb3JyZWN0ZWQgemlwIGNvZGVzIHNob3djYXNlIGEgc2lnbmlmaWNhbnQgZWZmb3J0IGRlZGljYXRlZCB0byBvcmdhbml6aW5nIHRoZSBhZGRyZXNzIGFuZCB6aXAgY29kZSBjb2x1bW5zLCB3aXRoIGEgMTAwJSBhY2N1cmFjeSByYXRlIGFjcm9zcyBhbG1vc3QgZm91ciB0aG91c2FuZCBjZWxscy4KCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjUwJSJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIvVXNlcnMvc2hhbWltYS9EZXNrdG9wL1Byb2plY3RfMS9pbWFnZXMvRGF0YTMucG5nIiwgZXJyb3IgPSBGQUxTRSkKCmBgYAoKVGhlIGltYWdlIGFib3ZlIGhpZ2hsaWdodHMgYSBtaXNzcGVsbGluZyBpbiB0aGUgUGV0cyBjb2x1bW4gcmVzdWx0aW5nIGZyb20gc2V2ZXJhbCB0eXBvLiBUbyByZXNvbHZlIHRoaXMgaXNzdWUsIHdlIGVtcGxveWVkIGNvcnJlY3RpdmUgbWVhc3VyZXMgdXNpbmcgUiBjb2RlIHRvIHJlY3RpZnkgYWxsIGVudHJpZXMgaW4gdGhlIFBldHMgY29sdW1uLgoKIyBDZW50cmFsIERhc2hib2FyZCAgCgpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSIxMDAlIn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi9Vc2Vycy9zaGFtaW1hL0Rlc2t0b3AvUHJvamVjdF8xL2ltYWdlcy9EYXNoYm9hcmQucG5nIiwgZXJyb3IgPSBGQUxTRSkKCmBgYApVdGlsaXppbmcgVGFibGVhdSwgSSBkZXNpZ25lZCBhIGNvbXByZWhlbnNpdmUgZGFzaGJvYXJkIHRvIHZpc3VhbGx5IGludGVycHJldCB0aGUgZGF0YXNldCwgd2l0aCB0aGUgZ29hbCBvZiBleHRyYWN0aW5nIG1lYW5pbmdmdWwgaW5zaWdodHMuIFRoZSBkYXNoYm9hcmQgcHJvbWluZW50bHkgcmV2ZWFscyB0aGF0IHRoZSBvcmdhbml6YXRpb24ncyBmb29kIGRpc3RyaWJ1dGlvbiBpcyBwcmltYXJpbHkgY2VudGVyZWQgaW4gSG91c3RvbiBhbmQgdmFyaW91cyBwYXJ0cyBvZiBUZXhhcy4KCkJ5IHNlZ21lbnRpbmcgdGhlIGRhdGEgYmFzZWQgb24gcGV0IHR5cGVzIGFuZCB6aXAgY29kZXMsIHRoZSBkYXNoYm9hcmQgb2ZmZXJzIGEgc3BlY2lmaWMgb3ZlcnZpZXcsIGhpZ2hsaWdodGluZyB3aGljaCB6aXAgY29kZXMgaGF2ZSBleHBlcmllbmNlZCB0aGUgaGlnaGVzdCBzZXJ2aWNlIGZvciBwZXRzIGFuZCB0aGUgY29ycmVzcG9uZGluZyB0eXBlcyBvZiBwZXRzIHByZXZhbGVudCBpbiB0aG9zZSBhcmVhcy4gVGhlIGFuYWx5c2lzIG9mIGRpc3RyaWJ1dGlvbiBieSBwZXQgdHlwZXMgaW4gY2l0aWVzIHByb3ZpZGVzIHZhbHVhYmxlIGluc2lnaHRzIGludG8gdGhlIG1ham9yIGNpdGllcyB0aGUgb3JnYW5pemF0aW9uIHNlcnZlcywgYXNzaXN0aW5nIGRlY2lzaW9uLW1ha2VycyBpbiBmb2N1c2luZyBvbiBzcGVjaWZpYyBhcmVhcy4KClRoZSBkaXN0cmlidXRpb24gb2Ygd2V0IGFuZCBkcnkgZm9vZHMgb3ZlciB0aGUgeWVhcnMgcHJvdmlkZXMgYSB0ZW1wb3JhbCB1bmRlcnN0YW5kaW5nIG9mIGhvdyBmb29kIGRpc3RyaWJ1dGlvbiBoYXMgZXZvbHZlZC4gUGFydGljdWxhcmx5IG5vdGV3b3J0aHkgaXMgdGhlIHNpZ25pZmljYW50IGluY3JlYXNlIGluIGZvb2QgZGlzdHJpYnV0aW9uIGR1cmluZyB0aGUgcGFuZGVtaWMgaW4gMjAyMCwgcmVmbGVjdGluZyB0aGUgb3JnYW5pemF0aW9uJ3MgaGVpZ2h0ZW5lZCBlZmZvcnRzIGR1cmluZyBjaGFsbGVuZ2luZyB0aW1lcy4gVGhpcyBkYXRhIGNhbiBwbGF5IGEgY3J1Y2lhbCByb2xlIGluIHBsYW5uaW5nIGNhbXBpbmcgYW5kIGZ1bmRyYWlzaW5nIGFjdGl2aXRpZXMuCgpFeGFtaW5pbmcgZm9vZCBkaXN0cmlidXRpb24gb24gYSBtb250aGx5IGJhc2lzIGZ1cnRoZXIgdW52ZWlscyB0cmVuZHMgaW4gZm9vZCBkZW1hbmQuIFRoZSBkYXNoYm9hcmQgaWxsdXN0cmF0ZXMgYSBwZWFrIGluIGRlbWFuZCBkdXJpbmcgSnVseSwgbWlkLXllYXIsIGFuZCBhbm90aGVyIHN1cmdlIHRvd2FyZHMgdGhlIGVuZCBvZiB0aGUgeWVhciBpbiBEZWNlbWJlci9KYW51YXJ5LiBUaGlzIGluZm9ybWF0aW9uIGlzIGVzc2VudGlhbCBmb3IgYWRhcHRpbmcgc3RyYXRlZ2llcyB0byBtZWV0IHZhcnlpbmcgZGVtYW5kIHRocm91Z2hvdXQgdGhlIHllYXIuCgojIyBEYXRhIFByZXBhcmF0aW9uIGFuZCBJc3N1ZQoKQ2VydGFpbiBjaGFsbGVuZ2VzIHdlcmUgZW5jb3VudGVyZWQgZHVyaW5nIHRoZSBkYXRhIHByZXBhcmF0aW9uIHBoYXNlIGZvciBkYXRhIGFuYWx5c2lzLiBUaGUgZGF0YXNldCBvcmlnaW5hdGVkIGluIDIwMDEsIGJ1dCBpdCB3YXMgb2JzZXJ2ZWQgdGhhdCB0aGUgZGF0YSBjb2xsZWN0aW9uIHByb2Nlc3Mgd2FzIG5vdCBhcyByaWdvcm91cyBpbiB0aGUgZWFybGllciB5ZWFycywgcmVzdWx0aW5nIGluIGEgcmVsYXRpdmVseSBzbWFsbGVyIGRhdGFzZXQgdW50aWwgMjAxMC4gTm90YWJseSwgdGhlcmUgd2VyZSBnYXBzIGluIHRoZSBkYXRhLCBwYXJ0aWN1bGFybHkgaW4gdGhlIHllYXIgMjAwMiB0byAyMDA1LCAyMDA3IHRvIDIwMDkuIENvbnNlcXVlbnRseSwgd2UgbWFkZSB0aGUgZGVjaXNpb24gdG8gZm9jdXMgb3VyIGFuYWx5c2lzIG9uIHRoZSBkYXRhIHN0YXJ0aW5nIGZyb20gMjAxMCwgZW5zdXJpbmcgYSBtb3JlIGNvbXByZWhlbnNpdmUgYW5kIHJlbGlhYmxlIGRhdGFzZXQgZm9yIG91ciBzdHVkeS4KClRvIGFkZHJlc3MgdGhpcywgd2UgbWV0aWN1bG91c2x5IHNlcGFyYXRlZCB0aGUgZGF0YXNldCBpbnRvIHNlZ21lbnRzLCBhbGxvY2F0aW5nIHNwZWNpZmljIHBvcnRpb25zIGZvciB0cmFpbmluZyBhbmQgdGVzdGluZyBwdXJwb3Nlcy4gVGhpcyBzdHJhdGVnaWMgZGl2aXNpb24gYWxsb3dlZCB1cyB0byB3b3JrIHdpdGggYSBtb3JlIGZvY3VzZWQgYW5kIHJvYnVzdCBkYXRhc2V0LCBlbnN1cmluZyB0aGUgYWNjdXJhY3kgYW5kIHJlbGlhYmlsaXR5IG9mIG91ciBhbmFseXNpcy4gQnkgY29uY2VudHJhdGluZyBvbiB0aGUgeWVhcnMgd2l0aCBtb3JlIGNvbnNpc3RlbnQgYW5kIHJlbGlhYmxlIGRhdGEgY29sbGVjdGlvbiBwcmFjdGljZXMsIHdlIGFpbWVkIHRvIGVuaGFuY2UgdGhlIHF1YWxpdHkgYW5kIHZhbGlkaXR5IG9mIG91ciBmaW5kaW5ncy4KYGBge3IsZWNobz1GQUxTRSxyZXN1bHRzPSdoaWRlJ30KCnBldF9kYXRhID0gcmVhZF94bHN4ICgiRnJpZW5kczRMaWZlLnhsc3giKQoKIyBDb252ZXJ0IERhdGUgY29sdW1uIHRvIHByb3BlciBEYXRlIGZvcm1hdApwZXRfZGF0YSREYXRlID0gYXMuRGF0ZShwZXRfZGF0YSREYXRlLCBmb3JtYXQgPSAiJW0vJWQvJVkiKQojaGVhZChwZXRfZGF0YSREYXRlKQojdGFpbChwZXRfZGF0YSREYXRlKQoKI2NvbG5hbWVzKHBldF9kYXRhKQojc3RyKHBldF9kYXRhKQoKIyBPcmRlciBEYXRlCnBldF9kYXRhPC0gcGV0X2RhdGFbb3JkZXIocGV0X2RhdGEkRGF0ZSkgLCBdCiNoZWFkKHBldF9kYXRhKQoKIyBFeHBsb3JlIHRoZSBzdHJ1Y3R1cmUgb2YgdGhlIGRhdGEKI3N0cihwZXRfZGF0YSkKCiMgU3VtbWFyeSBzdGF0aXN0aWNzIGZvciBudW1lcmljIGNvbHVtbnMKI3N1bW1hcnkocGV0X2RhdGEpCgojIENoZWNrIGZvciBtaXNzaW5nIHZhbHVlcwojY29sU3Vtcyhpcy5uYShwZXRfZGF0YSkpCgoKYGBgClxuZXdwYWdlCgojIEZvcmVjYXN0aW5nCgpJbiB0aGlzIHByb2plY3QsIG15IHByaW1hcnkgb2JqZWN0aXZlIGlzIHRvIGRldmVsb3AgYWNjdXJhdGUgZm9yZWNhc3RzIGZvciB0aGUgbW9udGhseSBkZW1hbmQgb2YgRHJ5IEZvb2RzIGFuZCBXZXQgRm9vZHMgdXNpbmcgdGltZSBzZXJpZXMgYW5hbHlzaXMgdGVjaG5pcXVlcy4gVG8gYWNoaWV2ZSB0aGlzLCBJIHdpbGwgZW1wbG95IHRoZSAqKkJveC1KZW5raW5zIE1ldGhvZG9sb2d5KiosIGEgd2lkZWx5IHJlc3BlY3RlZCBhcHByb2FjaCBmb3IgdGltZSBzZXJpZXMgZm9yZWNhc3RpbmcgQGVud2lraToxMDk3MzMyMDgwLgoKVGhlIGZpcnN0IHN0ZXAgaW52b2x2ZXMgYSB0aG9yb3VnaCBleGFtaW5hdGlvbiBvZiB0aGUgJ0ZyaWVuZHMgZm9yIExpZmUnIGRhdGFzZXQsIGV4cGxvcmluZyBpdHMgaGlzdG9yaWNhbCByZWNvcmRzIHRvIHVuZGVyc3RhbmQgdGhlIGJlaGF2aW9yIG9mIERyeSBGb29kcyBhbmQgV2V0IEZvb2RzIGRlbWFuZHMgb3ZlciB0aW1lLiBBQ0YgYW5kIFBBQ0YgcGxvdHMgd2lsbCBiZSBnZW5lcmF0ZWQgdG8gdW5jb3ZlciBhdXRvY29ycmVsYXRpb24gcGF0dGVybnMgd2l0aGluIHRoZSBkYXRhLCBjcnVjaWFsIGZvciBpZGVudGlmeWluZyBwb3RlbnRpYWwgc2Vhc29uYWxpdHkgYW5kIHRyZW5kIGNvbXBvbmVudHMuIEluIGNhc2UgdGhlIGRhdGFzZXQgbGFja3Mgc2Vhc29uYWxpdHksIEkgd2lsbCBpbXBsZW1lbnQgbG9nIHRyYW5zZm9ybWF0aW9uIHRvIHN0YWJpbGl6ZSB0aGUgZGF0YSBmb3IgYWNjdXJhdGUgZm9yZWNhc3RpbmcuCgpUaGUgZGF0YXNldCB3aWxsIGJlIHNwbGl0IGludG8gdHJhaW5pbmcgYW5kIHRlc3Rpbmcgc2V0cyB0byBmYWNpbGl0YXRlIHByZWNpc2UgbW9kZWwgZXZhbHVhdGlvbi4gRXNzZW50aWFsIHByZXByb2Nlc3Npbmcgc3RlcHMsIGluY2x1ZGluZyBoYW5kbGluZyBtaXNzaW5nIHZhbHVlcyBhbmQgb3V0bGllcnMsIHdpbGwgYmUgZXhlY3V0ZWQgdG8gZW5zdXJlIGRhdGEgaW50ZWdyaXR5LgoKSSB3aWxsIGxldmVyYWdlIHRoZSAqKmF1dG8tYXJpbWEqKiAoQXV0by1BdXRvcmVncmVzc2l2ZSBJbnRlZ3JhdGVkIE1vdmluZyBBdmVyYWdlICkgYWxnb3JpdGhtIHRvIGF1dG9tYXRpY2FsbHkgc3VnZ2VzdCBzdWl0YWJsZSBtb2RlbHMgYmFzZWQgb24gdGhlIGRhdGFzZXQncyBjaGFyYWN0ZXJpc3RpY3MuIFRoZSByZXNpZHVhbHMgd2lsbCBiZSBhbmFseXplZCB1c2luZyAqKlNBUklNQSoqIChTZWFzb25hbCBBdXRvcmVncmVzc2l2ZSBJbnRlZ3JhdGVkIE1vdmluZyBBdmVyYWdlKSBtb2RlbHMgdG8gY29uZmlybSB0aGUgYWJzZW5jZSBvZiBzeXN0ZW1hdGljIHBhdHRlcm5zLCBlbnN1cmluZyB0aGUgZm9yZWNhc3QncyByZWxpYWJpbGl0eS4gT25jZSB0aGUgbW9kZWxzIGFyZSBzZWxlY3RlZCBhbmQgdHJhaW5lZCBvbiB0aGUgdHJhaW5pbmcgZGF0YSwgd2Ugd2lsbCBwcm9jZWVkIHRvIGdlbmVyYXRlIG1vbnRobHkgZm9yZWNhc3RzIGZvciBEcnkgRm9vZHMgYW5kIFdldCBGb29kcyBkZW1hbmQuIFByZWRpY3Rpb25zIHdpbGwgYmUgY29tcGFyZWQgYWdhaW5zdCB0aGUgYWN0dWFsIHRlc3QgZGF0YSB0byBhc3Nlc3MgdGhlIG1vZGVsJ3MgYWNjdXJhY3kgYW5kIHJlbGlhYmlsaXR5LiBQZXJmb3JtYW5jZSBtZXRyaWNzIHN1Y2ggYXMgTWVhbiBBYnNvbHV0ZSBFcnJvciAoTUFFKSwgUm9vdCBNZWFuIFNxdWFyZWQgRXJyb3IgKFJNU0UpLCBhbmQgTUFQRSAoTWVhbiBBYnNvbHV0ZSBQZXJjZW50YWdlIEVycm9yKSB3aWxsIGJlIGNvbXB1dGVkIHRvIHF1YW50aWZ5IHRoZSBmb3JlY2FzdGluZyBhY2N1cmFjeS4KCgojIFN0YXRpc3RpY2FsIE1ldGhvZG9sb2d5CgojIyBUaW1lIFNlcmlzZXMgQW5hbHlzaXMKClRpbWUgc2VyaWVzIGFuYWx5c2lzIGlzIGEgc3RhdGlzdGljYWwgdGVjaG5pcXVlIHVzZWQgdG8gYW5hbHl6ZSBhbmQgZm9yZWNhc3QgZGF0YSBwb2ludHMgY29sbGVjdGVkIG9yIHJlY29yZGVkIGF0IHJlZ3VsYXIgdGltZSBpbnRlcnZhbHMuIEluIHRoZSBjb250ZXh0IG9mIHRoaXMgcHJvamVjdCwgd2hpY2ggaW52b2x2ZXMgZm9yZWNhc3RpbmcgbW9udGhseSBkZW1hbmQgZm9yIERyeSBGb29kIGFuZCBXZXQgRm9vZCBwcm9kdWN0cywgdGltZSBzZXJpZXMgYW5hbHlzaXMgd2lsbCBoZWxwIHRvIHVuY292ZXIgcGF0dGVybnMsIHRyZW5kcywgYW5kIHNlYXNvbmFsaXR5IHdpdGhpbiB0aGUgaGlzdG9yaWNhbCBkYXRhLiBHYXRoZXIgaGlzdG9yaWNhbCBkYXRhIG9uIG1vbnRobHkgRHJ5IEZvb2QgYW5kIFdldCBGb29kIGRlbWFuZC4gRWFjaCBkYXRhIHBvaW50IHJlcHJlc2VudHMgdGhlIGRlbWFuZCBmb3IgYSBzcGVjaWZpYyBtb250aCBbQGNoYXRmaWVsZDIwMDB0aW1lXS4KCiQkIHlfdCA9IFRfdCArIFNfdCArIGVfdCBcXAokJAokJApcdGV4dHtXaGVyZTp9XFwKXGJlZ2lue2FsaWduKn0KICAgIHlfdCAmIDogXHRleHR7VGltZSBzZXJpZXMgZnVuY3Rpb259IFxcCiAgICBUX3QgJiA6IFx0ZXh0e1RyZW5kfSBcXAogICAgU190ICYgOiBcdGV4dHtTZWFzb25hbGl0eX0gXFwKICAgIGVfdCAmIDogXHRleHR7UmVzaWR1YWx9ClxlbmR7YWxpZ24qfSAkJAoKCgpgYGB7cixmaWcud2lkdGg9Ni41LGZpZy5oZWlnaHQ9OCxlY2hvPUZBTFNFLHJlc3VsdHM9J2hpZGUnfQoKCiMgQ3JlYXRlIGEgdGltZSBzZXJpZXMgb2JqZWN0IGZvciBEcnkgRm9vZHMgZnJvbSB5ZWFyIG9mIDIwMDEKZHJ5Zm9vZF9kYXRhIDwtIHRzKHBldF9kYXRhJCJEcnkgRm9vZHMiLCBzdGFydCA9IGMoMjAwMSwgMSksIGVuZCA9IGMoMjAyMywgMiksIGZyZXF1ZW5jeSA9IDEyKSAgIyBBc3N1bWluZyBtb250aGx5IGRhdGEgKGZyZXF1ZW5jeT0xMikKCiMgQ3JlYXRlIGEgdGltZSBzZXJpZXMgb2JqZWN0IGZvciBXZXQgRm9vZHMKd2V0Zm9vZF9kYXRhIDwtIHRzKHBldF9kYXRhJCJXZXQgRm9vZHMiLCBzdGFydCA9IGMoMjAwMSwgMSksIGVuZCA9IGMoMjAyMywgMiksIGZyZXF1ZW5jeSA9IDEyKSAgIyBBc3N1bWluZyBtb250aGx5IGRhdGEgKGZyZXF1ZW5jeT0xMikKCiNhdXRvcGxvdCh3ZXRmb29kX2RhdGEpCiMgQ3JlYXRlIGEgdGltZSBzZXJpZXMgcGxvdCBmb3IgYm90aCBEcnkgRm9vZHMgYW5kIFdldCBmb29kcyBDb25zdW1wdGlvbgpwYXIobWZyb3c9YygzLDEpKQpwbG90LnRzKGRyeWZvb2RfZGF0YSwgbWFpbiA9ICJEcnkgRm9vZHMgQ29tc3VtcHRpb24gT3ZlciBUaW1lIixjZXgubWFpbj0xLjUsIGNleC5sYWI9MywgY2V4LmF4aXM9MykKcGxvdC50cyh3ZXRmb29kX2RhdGEsIG1haW4gPSAiV2V0IEZvb2RzIENvbXN1bXB0aW9uIE92ZXIgVGltZSIsY2V4Lm1haW49MS41LCBjZXgubGFiPTMsIGNleC5heGlzPTMpCmBgYApUaGUgcGxvdCBleGhpYml0ZWQgYW4gaW5jcmVhc2UgaW4gdmFyaWFiaWxpdHkgb3ZlciB0aW1lLCBpbmRpY2F0aW5nIHRoYXQgdGhlIGRpc3BlcnNpb24gb2YgdGhlIGRhdGEgcG9pbnRzIHdhcyBub3QgY29uc3RhbnQuIFN1Y2ggY2hhcmFjdGVyaXN0aWNzIGluIHRoZSBkYXRhIGNhbiBwb3NlIGNoYWxsZW5nZXMgZm9yIGFjY3VyYXRlIG1vZGVsaW5nIGFuZCBmb3JlY2FzdGluZy4KClxuZXdwYWdlCgpgYGB7ciwgZmlnLndpZHRoPTYuNSxmaWcuaGVpZ2h0PTgsZWNobz1GQUxTRX0KCgojTG9nLVRyYW5zZm9ybWVkIERyeSBGb29kcwpkcnlmb29kX2RhdGEgPC0gdHMobG9nKHBldF9kYXRhJCJEcnkgRm9vZHMiKSwgc3RhcnQgPSBjKDIwMDEsIDEpLCBlbmQgPSBjKDIwMjMsIDIpLCBmcmVxdWVuY3kgPSAxMikgICMgQXNzdW1pbmcgbW9udGhseSBkYXRhIChmcmVxdWVuY3k9MTIpCgojIExvZy1UcmFuc2Zvcm1lZCBXZXQgRm9vZAp3ZXRmb29kX2RhdGEgPC0gdHMobG9nKHBldF9kYXRhJCJXZXQgRm9vZHMiKSwgc3RhcnQgPSBjKDIwMDEsIDEpLCBlbmQgPSBjKDIwMjMsIDIpLCBmcmVxdWVuY3kgPSAxMikgICMgQXNzdW1pbmcgbW9udGhseSBkYXRhIChmcmVxdWVuY3k9MTIpCgoKcGFyKG1mcm93PWMoMywxKSkKCnBsb3QoZHJ5Zm9vZF9kYXRhLCBtYWluID0gIkxvZy1UcmFuc2Zvcm1lZCBEcnkgRm9vZHMgQ29uc3VtcHRpb24gT3ZlciBUaW1lIiwgeGxhYiA9ICJZZWFyIiwgeWxhYiA9ICJMb2coRHJ5IEZvb2RzKSIpCgoKcGxvdCh3ZXRmb29kX2RhdGEsIG1haW4gPSAiTG9nLVRyYW5zZm9ybWVkIFdldCBGb29kcyBDb25zdW1wdGlvbiBPdmVyIFRpbWUiLCB4bGFiID0gIlllYXIiLCB5bGFiID0gIkxvZyhXZXQgRm9vZHMpIikKCgpgYGAKIyMgTG9nLVRyYW5zZm9ybWVkIERhdGEgCgpMb2cgdHJhbnNmb3JtYXRpb24gaXMgdXNlZCBpbiB0aW1lIHNlcmllcyBhbmFseXNpcyB0byBzdGFiaWxpemUgdGhlIHZhcmlhbmNlIGFuZCBwcm9tb3RlIHN0YXRpb25hcml0eS4gU3RhdGlvbmFyaXR5IGlzIGEgZGVzaXJhYmxlIHByb3BlcnR5IGluIHRpbWUgc2VyaWVzIGRhdGEsIHdoZXJlIHN0YXRpc3RpY2FsIHByb3BlcnRpZXMgc3VjaCBhcyBtZWFuIGFuZCB2YXJpYW5jZSByZW1haW4gY29uc3RhbnQgb3ZlciB0aW1lLiBMb2cgdHJhbnNmb3JtYXRpb24gaGVscHMgYWNoaWV2ZSB0aGlzIGJ5IGFkZHJlc3NpbmcgaXNzdWVzIGxpa2UgaGV0ZXJvc2NlZGFzdGljaXR5LCB3aGljaCBpcyB0aGUgcHJlc2VuY2Ugb2YgY2hhbmdpbmcgdmFyaWFuY2UgaW4gdGhlIGRhdGEuCgpUaGUgbG9nIHRyYW5zZm9ybWF0aW9uIG9mIHRoZSBEcnkgRm9vZHMgYW5kIFdldCBGb29kcyBkYXRhIGlzIGEgY3J1Y2lhbCBzdGVwIGluIGVuaGFuY2luZyBpdHMgc3RhYmlsaXR5LCBpbnRlcnByZXRhYmlsaXR5LCBhbmQgc3VpdGFiaWxpdHkgZm9yIGZ1cnRoZXIgdGltZSBzZXJpZXMgYW5hbHlzaXMgYW5kIGZvcmVjYXN0aW5nIGluIHRoaXMgcHJvamVjdC4gQWZ0ZXIgaW1wbGVtZW50aW5nIHRoZSAqKmxvZ2FyaXRobWljIHRyYW5zZm9ybWF0aW9uKiosIHRoZSByZXN1bHRpbmcgcGxvdCBkaXNwbGF5ZWQgYSBtb3JlIHN0YWJpbGl6ZWQgYW5kIHBvdGVudGlhbGx5IHN0YXRpb25hcnkgcGF0dGVybi4gVGhlIGRhdGEgZXhoaWJpdGVkIHJlZHVjZWQgdmFyaWFuY2UsIGFuZCBhIGNvbnNpc3RlbnQgbWVhbiBwYXR0ZXJuIGVtZXJnZWQsIHN1Z2dlc3RpbmcgYSBzdGF0aW9uYXJ5IGJlaGF2aW9yLiBUaGlzIHN0YWJpbGl6ZWQgZGF0YXNldCBmb3JtcyBhIG1vcmUgcmVsaWFibGUgZm91bmRhdGlvbiBmb3Igc3Vic2VxdWVudCB0aW1lIHNlcmllcyBhbmFseXNpcy4KClRoZSBsb2cgdHJhbnNmb3JtYXRpb24gbm90IG9ubHkgYWRkcmVzc2VzIGNvbmNlcm5zIHJlbGF0ZWQgdG8gdmFyaWFuY2UgaW5zdGFiaWxpdHkgYnV0IGFsc28gaW1wcm92ZXMgdGhlIGludGVycHJldGFiaWxpdHkgb2YgdGhlIGRhdGEgQGJvZWhtMjAxNHByb21vdGluZy4gQnkgcHJvbW90aW5nIHN0YXRpb25hcml0eSwgdGhpcyB0cmFuc2Zvcm1hdGlvbiBsYXlzIHRoZSBncm91bmR3b3JrIGZvciBjb25kdWN0aW5nIHJvYnVzdCBhbmQgYWNjdXJhdGUgdGltZSBzZXJpZXMgYW5hbHlzaXMuIENvbnNlcXVlbnRseSwgaXQgZmFjaWxpdGF0ZXMgZWZmZWN0aXZlIGZvcmVjYXN0aW5nIGluIHRoZSBsYXRlciBzdGFnZXMgb2YgdGhlIHByb2plY3QuCgojIyBEYXRhIFByZXBhcmF0aW9uIGFuZCBJc3N1ZQoKQ2VydGFpbiBjaGFsbGVuZ2VzIHdlcmUgZW5jb3VudGVyZWQgZHVyaW5nIHRoZSBkYXRhIHByZXBhcmF0aW9uIHBoYXNlIGZvciBkYXRhIGFuYWx5c2lzLiBUaGUgZGF0YXNldCBvcmlnaW5hdGVkIGluIDIwMDEsIGJ1dCBpdCB3YXMgb2JzZXJ2ZWQgdGhhdCB0aGUgZGF0YSBjb2xsZWN0aW9uIHByb2Nlc3Mgd2FzIG5vdCBhcyByaWdvcm91cyBpbiB0aGUgZWFybGllciB5ZWFycywgcmVzdWx0aW5nIGluIGEgcmVsYXRpdmVseSBzbWFsbGVyIGRhdGFzZXQgdW50aWwgMjAxMC4gTm90YWJseSwgdGhlcmUgd2VyZSBnYXBzIGluIHRoZSBkYXRhLCBwYXJ0aWN1bGFybHkgaW4gdGhlIHllYXIgMjAwMiB0byAyMDA1LCAyMDA3IHRvIDIwMDkuIENvbnNlcXVlbnRseSwgSSBtYWRlIHRoZSBkZWNpc2lvbiB0byBmb2N1cyB0aGlzIGFuYWx5c2lzIG9uIHRoZSBkYXRhIHN0YXJ0aW5nIGZyb20gMjAxMCwgZW5zdXJpbmcgYSBtb3JlIGNvbXByZWhlbnNpdmUgYW5kIHJlbGlhYmxlIGRhdGFzZXQgZm9yIHRoaXMgc3R1ZHkuCgpUbyBhZGRyZXNzIHRoaXMsIHdlIG1ldGljdWxvdXNseSBzZXBhcmF0ZWQgdGhlIGRhdGFzZXQgaW50byBzZWdtZW50cywgYWxsb2NhdGluZyBzcGVjaWZpYyBwb3J0aW9ucyBmb3IgdHJhaW5pbmcgYW5kIHRlc3RpbmcgcHVycG9zZXMuIFRoaXMgc3RyYXRlZ2ljIGRpdmlzaW9uIGFsbG93ZWQgdXMgdG8gd29yayB3aXRoIGEgbW9yZSBmb2N1c2VkIGFuZCByb2J1c3QgZGF0YXNldCwgZW5zdXJpbmcgdGhlIGFjY3VyYWN5IGFuZCByZWxpYWJpbGl0eSBvZiBvdXIgYW5hbHlzaXMuIEJ5IGNvbmNlbnRyYXRpbmcgb24gdGhlIHllYXJzIHdpdGggbW9yZSBjb25zaXN0ZW50IGFuZCByZWxpYWJsZSBkYXRhIGNvbGxlY3Rpb24gcHJhY3RpY2VzLCB3ZSBhaW1lZCB0byBlbmhhbmNlIHRoZSBxdWFsaXR5IGFuZCB2YWxpZGl0eSBvZiBvdXIgZmluZGluZ3MuCgojIyMgU3BsaXRpbmcgRGF0YQoKRm9yIHRoZSBEcnkgRm9vZCBkYXRhc2V0LCA5NSUgb2YgdGhlIGRhdGEgd2FzIGFsbG9jYXRlZCBmb3IgdHJhaW5pbmcsIHdoaWxlIDUlIHdhcyByZXNlcnZlZCBmb3IgdGVzdGluZywgZW5zdXJpbmcgYSB0aG9yb3VnaCBhbmQgcm9idXN0IGV2YWx1YXRpb24uIFNpbWlsYXJseSwgdGhlIFdldCBGb29kIGRhdGFzZXQgZW1wbG95ZWQgYSBzcGxpdCBvZiA5OCUgZm9yIHRyYWluaW5nIGFuZCAyJSBmb3IgdGVzdGluZywgY29udHJpYnV0aW5nIHRvIHRoZSBlbmhhbmNlbWVudCBvZiB0aGUgbW9kZWwncyBwcmVkaWN0aXZlIGFjY3VyYWN5LgoKYGBge3IsZWNobz1GQUxTRSxyZXN1bHRzPSdoaWRlJ30KIyBEcnkgRm9vZHMKIyBDcmVhdGUgYSB0aW1lIHNlcmllcyBvYmplY3QgZm9yIERyeSBGb29kcyBmcm9tIHRoZSB5ZWFyIDIwMTAKI2RyeWZvb2RfZGF0YSA9IGxvZyhkcnlmb29kX2RhdGEpCmRyeWZvb2RfZGF0YSA8LSB0cyhsb2cocGV0X2RhdGEkIkRyeSBGb29kcyIpLCBzdGFydCA9IGMoMjAxMCwgMSksIGVuZCA9IGMoMjAyMywgMiksIGZyZXF1ZW5jeSA9IDEyKSAgIyBBc3N1bWluZyBtb250aGx5IGRhdGEgKGZyZXF1ZW5jeT0xMikKCiMgU2V0IHRoZSBzcGxpdCBwb2ludCAoZS5nLiwgOTUlIGZvciB0cmFpbmluZywgNSUgZm9yIHRlc3RpbmcpCnNwbGl0X3BvaW50IDwtIGZsb29yKDAuOTUgKiBsZW5ndGgoZHJ5Zm9vZF9kYXRhKSkKCiMgU3BsaXQgdGhlIGRhdGEgaW50byB0cmFpbmluZyBhbmQgdGVzdGluZyBzZXRzCmRyeWZvb2QgPC0gd2luZG93KGRyeWZvb2RfZGF0YSwgc3RhcnQgPSBzdGFydChkcnlmb29kX2RhdGEpLCBlbmQgPSB0aW1lKGRyeWZvb2RfZGF0YSlbc3BsaXRfcG9pbnRdKQoKIyBDcmVhdGUgdGhlIHRlc3RpbmcgZGF0YQpkcnlmb29kX3Rlc3QgPC0gd2luZG93KGRyeWZvb2RfZGF0YSwgc3RhcnQgPSB0aW1lKGRyeWZvb2RfZGF0YSlbc3BsaXRfcG9pbnQgKyAxXSkKCiMgQ2hlY2sgdGhlIGxlbmd0aHMgb2YgdHJhaW5pbmcgYW5kIHRlc3RpbmcgZGF0YQpsZW5ndGgoZHJ5Zm9vZCkKbGVuZ3RoKGRyeWZvb2RfdGVzdCkKaGVhZChkcnlmb29kX3Rlc3QpCnRhaWwoZHJ5Zm9vZF90ZXN0KQoKIyBDcmVhdGUgYSB0aW1lIHNlcmllcyBvYmplY3QgZm9yIFdldEZvb2RzIGZyb20gdGhlIHllYXIgMjAxMAp3ZXRmb29kX2RhdGEgPC0gdHMobG9nKHBldF9kYXRhJCJXZXQgRm9vZHMiKSwgc3RhcnQgPSBjKDIwMTAsIDEpLCBlbmQgPSBjKDIwMjMsIDIpLCBmcmVxdWVuY3kgPSAxMikgICMgQXNzdW1pbmcgbW9udGhseSBkYXRhIChmcmVxdWVuY3k9MTIpCgojIFNldCB0aGUgc3BsaXQgcG9pbnQgKGUuZy4sIDk4JSBmb3IgdHJhaW5pbmcsIDIlIGZvciB0ZXN0aW5nKQpzcGxpdF9wb2ludCA8LSBmbG9vcigwLjk4ICogbGVuZ3RoKHdldGZvb2RfZGF0YSkpCgojIFNwbGl0IHRoZSBkYXRhIGludG8gdHJhaW5pbmcgYW5kIHRlc3Rpbmcgc2V0cwp3ZXRmb29kIDwtIHdpbmRvdyh3ZXRmb29kX2RhdGEsIHN0YXJ0ID0gc3RhcnQod2V0Zm9vZF9kYXRhKSwgZW5kID0gdGltZSh3ZXRmb29kX2RhdGEpW3NwbGl0X3BvaW50XSkKCiMgQ3JlYXRlIHRoZSB0ZXN0aW5nIGRhdGEKd2V0Zm9vZF90ZXN0IDwtIHdpbmRvdyh3ZXRmb29kX2RhdGEsIHN0YXJ0ID0gdGltZSh3ZXRmb29kX2RhdGEpW3NwbGl0X3BvaW50ICsgMV0pCgojIENoZWNrIHRoZSBsZW5ndGhzIG9mIHRyYWluaW5nIGFuZCB0ZXN0aW5nIGRhdGEKI2xlbmd0aCh0cmFpbl9kYXRhKQojbGVuZ3RoKHRlc3RfZGF0YSkKCmBgYAoKIyBCb3gtSmVua2lucyBNZXRob2QKCkluIHRoZSBmb2xsb3dpbmcgcGFnZXMgSSB3aWxsIGZvbGxvdyB0aGUgQm94LUplbmtpbnMgTWV0aG9kIHRvIGlkZW50aWZ5IGFuZCBldmFsdWF0ZSBtb2RlbHMgZm9yIGZvcmVjYXN0aW5nLiBUaGUgKipCb3gtSmVua2lucyBNZXRob2QqKiwgYWxzbyBrbm93biBhcyB0aGUgQm94LUplbmtpbnMgYXBwcm9hY2ggb3IgQm94LUplbmtpbnMgbWV0aG9kb2xvZ3ksIGlzIGEgc3lzdGVtYXRpYyBhbmQgd2lkZWx5IHVzZWQgdGVjaG5pcXVlIGZvciB0aW1lIHNlcmllcyBhbmFseXNpcyBhbmQgZm9yZWNhc3RpbmcuIERldmVsb3BlZCBieSBHZW9yZ2UgQm94IGFuZCBHd2lseW0gSmVua2lucyBpbiB0aGUgZWFybHkgMTk3MHMsIHRoaXMgbWV0aG9kIGlzIHBhcnRpY3VsYXJseSBlZmZlY3RpdmUgZm9yIG1vZGVsaW5nIGFuZCBwcmVkaWN0aW5nIHVuaXZhcmlhdGUgdGltZSBzZXJpZXMgZGF0YS4gVGhlIGtleSBjb21wb25lbnRzIG9mIHRoZSBCb3gtSmVua2lucyBNZXRob2QgaW5jbHVkZTogCgoqIE1vZGVsIGlkZW50aWZpY2F0aW9uCiogTW9kZWwgZXN0aW1hdGlvbiBhbmQgCiogRGlhZ25vc3RpYyBjaGVja2luZwoKVG8gaW5pdGlhdGUgdGhpcyBwcm9jZXNzIGZvciBib3RoIERyeSBGb29kcyBhbmQgV2V0IEZvb2RzIGRhdGEsIEkgd2lsbCBiZWdpbiBieSBvYnNlcnZpbmcgdGhlIEFDRiBhbmQgUEFDRi4gVGhpcyBpbml0aWFsIGV4cGxvcmF0aW9uIGFpbXMgdG8gdW5kZXJzdGFuZCB0aGUgZGF0YSdzIGJlaGF2aW9yIGFuZCBhc3Nlc3MgaXRzIHN1aXRhYmlsaXR5IGZvciBtb2RlbGluZy4gQWZ0ZXIgdGhhdCBJIHdpbGwgcHJvY2VlZCB0byBlc3RpbWF0ZSBhbiBBUklNQSBtb2RlbCB1c2luZyB0aGUgYXV0by1hcmltYSBmdW5jdGlvbiwgd2hpY2ggc3VnZ2VzdHMgYW4gYXBwcm9wcmlhdGUgbW9kZWwgYmFzZWQgb24gdGhlIG9ic2VydmVkIEFDRiBhbmQgUEFDRi4gRm9sbG93aW5nIG1vZGVsIGVzdGltYXRpb24sIHRob3JvdWdoIGNoZWNrcyBvbiB0aGUgcmVzaWR1YWxzIHdpbGwgYmUgY29uZHVjdGVkIHRvIGVuc3VyZSB0aGUgbW9kZWwncyBhZGVxdWFjeS4KCiMgTW9kZWwgSWRlbnRpZmljYXRpb24KCiMjIEFuYWx5emluZyBBQ0YgYW5kIFBBQ0YKCkFDRiBhbmQgUEFDIGFyZSBlc3NlbnRpYWwgdG9vbHMgaW4gdGltZSBzZXJpZXMgYW5hbHlzaXMsIGVzcGVjaWFsbHkgd2hlbiBkZWFsaW5nIHdpdGggc3RhdGlvbmFyeSBkYXRhIGxpa2Ugb3VyIERyeSBGb29kIGFuZCBXZXQgRm9vZCBkYXRhc2V0LgoKQXV0b0NvcnJlbGF0aW9uIEZ1bmN0aW9uIChBQ0YpOgpBQ0YgbWVhc3VyZXMgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gYSB0aW1lIHNlcmllcyBhbmQgaXRzIGxhZ2dlZCB2YWx1ZXMuSW4gYSBzdGF0aW9uYXJ5IHNlcmllcywgQUNGIGhlbHBzIGlkZW50aWZ5IHBhdHRlcm5zIGFuZCBkZXBlbmRlbmNpZXMgaW4gdGhlIGRhdGEgb3ZlciBkaWZmZXJlbnQgdGltZSBsYWdzLiBUeXBpY2FsbHksIGhvcml6b250YWwgbGluZXMgYXJlIGRyYXduIG9uIHRoZSBBQ0YgcGxvdCB0byBpbmRpY2F0ZSB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbHMuIFBvaW50cyBvdXRzaWRlIHRoZXNlIGxpbmVzIHN1Z2dlc3Qgc2lnbmlmaWNhbnQgYXV0b2NvcnJlbGF0aW9uLgpFcXVhdGlvbjoKCiQkIEFDRihoKSA9IFxmcmFje1xzdW1fe3Q9MX1ee1QtaH0oeV90IC0gXGJhcnt5fSkoeV97dCtofSAtIFxiYXJ7eX0pfXtcc3VtX3t0PTF9XntUfSh5X3QgLSBcYmFye3l9KV4yfSBcXApcdGV4dHtXaGVyZTp9ClxcICB5X3RcIGlzXCB0aGVcIHZhbHVlXCBvZlwgdGhlXCB0aW1lXCBzZXJpZXNcIGF0XCB0aW1lXCB0LgpcXCBcYmFye3l9XCBpc1wgdGhlXCBtZWFuXCBvZlwgdGhlXCAgdGltZVwgc2VyaWVzLgpcXCBUXCAgaXNcICB0aGVcICB0b3RhbFwgIG51bWJlclwgIG9mIFwgb2JzZXJ2YXRpb25zXCAgaW5cIHRoZVwgIHRpbWVcICBzZXJpZXMuIFxcICQkCgpQYXJ0aWFsIEF1dG9Db3JyZWxhdGlvbiBGdW5jdGlvbiAoUEFDRik6ClBBQ0YgbWVhc3VyZXMgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gYSB0aW1lIHNlcmllcyBhbmQgaXRzIGxhZ2dlZCB2YWx1ZXMsIHJlbW92aW5nIHRoZSBlZmZlY3Qgb2YgaW50ZXJtZWRpYXRlIGxhZ3MuUEFDRiBpcyB1c2VmdWwgZm9yIGlkZW50aWZ5aW5nIHRoZSBkaXJlY3QgcmVsYXRpb25zaGlwcyBiZXR3ZWVuIG9ic2VydmF0aW9ucyBhdCBkaWZmZXJlbnQgdGltZSBwb2ludHMsIGV4Y2x1ZGluZyB0aGUgaW5mbHVlbmNlIG9mIG90aGVyIGxhZ3MuU2ltaWxhciB0byBBQ0YsIGhvcml6b250YWwgbGluZXMgYXJlIHVzZWQgYXMgcmVmZXJlbmNlIGZvciBzdGF0aXN0aWNhbCBzaWduaWZpY2FuY2UuCkVxdWF0aW9uOgoKJCQgUEFDRihoKSA9IFxmcmFje1x0ZXh0e2Nvdn0oeV90LCB5X3t0LWh9fFx7eV97dC0xfSwgeV97dC0yfSwgXGxkb3RzLCB5X3t0LWgrMX1cfSl9e1xzcXJ0e1x0ZXh0e3Zhcn0oeV90KVx0ZXh0e3Zhcn0oeV97dC1ofXxce3lfe3QtMX0sIHlfe3QtMn0sIFxsZG90cywgeV97dC1oKzF9XH0pfX0gXFwKJCQKJCRcdGV4dHtXaGVyZTp9ClxcIGNvdih5X3QsIHlfe3QtaH18XHt5X3t0LTF9LCB5X3t0LTJ9LCBcbGRvdHMsIHlfe3QtaCsxfVx9KSBpc1wgdGhlXCBjb25kaXRpb25hbFwgY292YXJpYW5jZVwgYmV0d2VlblwgeV90XCBhbmRcIHlfe3QtaH1cIGdpdmVuXCAgdGhlXCAgdmFsdWVzXCAgYXRcICBpbnRlcm1lZGlhdGVcICBsYWdzClxcIHZhcih5X3QpIGlzXCB0aGVcIHVuY29uZGl0aW9uYWxcIHZhcmlhbmNlXCBvZlwgeV90CiBcXCB7dmFyfSh5X3t0LWh9fFx7eV97dC0xfSwgeV97dC0yfSwgXGxkb3RzLCB5X3t0LWgrMX1cfVwgaXNcIHRoZVwgY29uZGl0aW9uYWxcIHZhcmlhbmNlXCBvZlwgeV97dC1ofVwgZ2l2ZW5cIHRoZVwgdmFsdWVzXCBhdFwgaW50ZXJtZWRpYXRlXCBsYWdzLiBcXCAkJAogCgpgYGB7ciwgZmlnLndpZHRoPTcsZmlnLmhlaWdodD0zLGVjaG89RkFMU0V9CiMgTG9hZCBuZWNlc3NhcnkgbGlicmFyaWVzCmxpYnJhcnkoZm9yZWNhc3QpCmxpYnJhcnkoZ2dwbG90MikKIyMjIyBEcnkgRm9vZHMgIyMjIyMKIyBQbG90IEFDRiBhbmQgUEFDRiBzaWRlIGJ5IHNpZGUKcGFyKG1mcm93PWMoMSwyKSkKCiMgUGxvdCBBQ0YgZm9yIERyeSBGb29kcwphY2YoZHJ5Zm9vZCxsYWcubWF4ID0gMTIsICBtYWluID0gIkFDRiBmb3IgRHJ5IEZvb2RzIikKCiMgUGxvdCBQQUNGIGZvciBEcnkgRm9vZHMKcGFjZihkcnlmb29kLCBwYWNmID0gVFJVRSwgbGFnLm1heCA9IDEyLCBtYWluID0gIlBBQ0YgZm9yIERyeSBGb29kcyIpCgpgYGAKQUNGIGFuZCBQQUNGIHBsb3RzIGZvciBEcnkgRm9vZHMgZGF0YSBpcyB3aXRoaW4gdGhlIGd1aWRlZCBsaW5lcyB3aGljaCBtZWFuIGRhdGEgaXMgc3RhdGlvbmFyeSBhbmQgaXQgaXMgYSBwb3NpdGl2ZSBzaWduLiBJdCBpbXBsaWVzIHRoYXQgdGhlcmUgYXJlIG5vIHNpZ25pZmljYW50IGF1dG9jb3JyZWxhdGlvbnMgYmV5b25kIHRoZSBmaXJzdCBsYWcsIGluZGljYXRpbmcgdGhhdCB0aGUgaGlzdG9yaWNhbCB2YWx1ZXMgb2YgdGhlIHNlcmllcyBkbyBub3QgY29udHJpYnV0ZSBzaWduaWZpY2FudGx5IHRvIHRoZSBjdXJyZW50IG9ic2VydmF0aW9uLiAKCmBgYHtyLGZpZy53aWR0aD03LGZpZy5oZWlnaHQ9MyxlY2hvPUZBTFNFfQojIyMjIFdldCBGb29kcyAjIyMjIwojIFBsb3QgQUNGIGFuZCBQQUNGIHNpZGUgYnkgc2lkZQpwYXIobWZyb3c9YygxLDIpKQoKIyBQbG90IEFDRiBmb3IgV2V0IEZvb2RzCmFjZih3ZXRmb29kLCBsYWcubWF4ID0gMTIsIG1haW4gPSAiQUNGIGZvciBXZXQgRm9vZHMiKQoKIyBQbG90IFBBQ0YgZm9yIERyeSBGb29kcwpwYWNmKHdldGZvb2QsIGxhZy5tYXggPSAxMiwgbWFpbiA9ICJQQUNGIGZvciBXZXQgRm9vZHMiKQoKYGBgCgpUaGUgQUNGIGFuZCBQQUNGIGZvciBXZXQgRm9vZHMgZGF0YSBjdXQgb2ZmIGFmdGVyIHRoZSBmaXJzdCBsYWcsIGl0IGluZGljYXRlcyB0aGF0IHRoZXJlIGlzIGxpa2VseSBubyBzaWduaWZpY2FudCBhdXRvY29ycmVsYXRpb24gb3IgcGFydGlhbCBhdXRvY29ycmVsYXRpb24gYmV5b25kIHRoZSBmaXJzdCBsYWcuVGhpcyBpbXBsaWVzIHRoYXQgdGhlIHdldCBmb29kIGRhdGEgaXMgc3RhdGlvbmFyeSwgZG8gbm90IGV4aGliaXQgYSBwZXJzaXN0ZW50IHRyZW5kIG9yIHBhdHRlcm4gb3ZlciB0aW1lLiBUaGlzIG9ic2VydmF0aW9uIHByb3ZpZGVzIGNvbmZpZGVuY2UgaW4gdGhlIHN0YWJpbGl0eSBvZiB0aGUgd2V0IGZvb2QgY29uc3VtcHRpb24gcGF0dGVybiBhbmQgYWxsb3dzIHVzIHRvIHByb2NlZWQgd2l0aCBtb2RlbGluZyBlZmZvcnRzLCBmb2N1c2luZyBvbiB0aGUgcHJpbWFyeSBkZXBlbmRlbmNpZXMgY2FwdHVyZWQgYnkgdGhlIGZpcnN0IGxhZy4gClxuZXdwYWdlCgojICBNb2RlbCBFc3RpbWF0aW9uCgojIyBBUklNQSBNb2RlbAoKVGhlIEF1dG9SZWdyZXNzaXZlIEludGVncmF0ZWQgTW92aW5nIEF2ZXJhZ2UgKCpBUklNQSopIGlzIGEgd2lkZWx5IHVzZWQgdGltZSBzZXJpZXMgYW5hbHlzaXMgYW5kIGZvcmVjYXN0aW5nIG1vZGVsLiBJdCBjb21iaW5lcyB0aHJlZSBrZXkgY29tcG9uZW50cyB0byBjYXB0dXJlIGRpZmZlcmVudCBhc3BlY3RzIG9mIHRpbWUgc2VyaWVzIGRhdGE6IEF1dG9SZWdyZXNzaXZlIChBUiksIEludGVncmF0ZWQgKEkpLCBhbmQgTW92aW5nIEF2ZXJhZ2UgKE1BKS4KClRoZSBtb2RlbGluZyBhcHByb2FjaCB3aWxsIGJlIHRvIHVzZSB0aGUgYXV0by5hcmltYSBmdW5jdGlvbiBmcm9tIHRoZSBmb3JlY2FzdCBwYWNrYWdlIHRvIHN1Z2dlc3QgbW9kZWxzIGZvciBlYWNoIERyeSBGb29kcyBhbmQgV2V0IEZvb2RzIHNjZW5hcmlvLiBBdXRvcmVncmVzc2l2ZSBJbnRlZ3JhdGVkIE1vdmluZyBBdmVyYWdlIE1vZGVsICoqQVJJTUEqKiAgaXMgYSB0aW1lIHNlcmllcyBhbmFseXNpcyBhbmQgZm9yZWNhc3RpbmcgbWV0aG9kLFRoZSBBUklNQSBtb2RlbCBpcyBkZW5vdGVkIGFzIEFSSU1BKHAsIGQsIHEpLCAKd2hlcmU6CnA6IEl0IGlzIHRoZSBvcmRlciBvZiB0aGUgYXV0b3JlZ3Jlc3NpdmUgcGFydCAoQVIpLgpkOiBUaGUgZGVncmVlIG9mIGRpZmZlcmVuY2luZyBuZWVkZWQgdG8gbWFrZSB0aGUgdGltZSBzZXJpZXMgZGF0YSBzdGF0aW9uYXJ5LgpxOiBUaGUgb3JkZXIgb2YgdGhlIG1vdmluZyBhdmVyYWdlIHBhcnQgKE1BKS4KVGhlIEFSSU1BIG1vZGVsIGlzIHBvd2VyZnVsIGZvciBoYW5kbGluZyBhIHdpZGUgcmFuZ2Ugb2YgdGltZSBzZXJpZXMgcGF0dGVybnMsIGluY2x1ZGluZyB0cmVuZCwgc2Vhc29uYWxpdHksIGFuZCBjeWNsaWMgcGF0dGVybnMuIEl0IGlzIHdpZGVseSB1c2VkIGZvciBmb3JlY2FzdGluZyBmdXR1cmUgdmFsdWVzIGJhc2VkIG9uIGhpc3RvcmljYWwgb2JzZXJ2YXRpb25zLgoKCkFSOgpBdXRvUmVncmVzc2l2ZSAoQVIpIHJlcHJlc2VudHMgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSBjdXJyZW50IG9ic2VydmF0aW9uIGFuZCBpdHMgcHJldmlvdXMgb2JzZXJ2YXRpb25zLCB3aXRoIHRoZSBpZGVhIHRoYXQgcGFzdCB2YWx1ZXMgY2FuIGJlIHVzZWZ1bCBpbiBwcmVkaWN0aW5nIGZ1dHVyZSB2YWx1ZXMuIAoKJCQgeV90ID0gXHBoaV8xIHlfe3QtMX0gKyBccGhpXzIgeV97dC0yfSArIFxsZG90cyArIFxwaGlfcCB5X3t0LXB9ICsgXHZhcmVwc2lsb25fdCBcXCAkJApNQToKTW92aW5nIEF2ZXJhZ2UgKE1BKSByZXByZXNlbnRzIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgY3VycmVudCBvYnNlcnZhdGlvbiBhbmQgYSByZXNpZHVhbCBlcnJvciBmcm9tIGEgbW92aW5nIGF2ZXJhZ2UgbW9kZWwgYXBwbGllZCB0byBwYXN0IG9ic2VydmF0aW9ucy4KCiQkIHlfdCA9IFx2YXJlcHNpbG9uX3QgLSBcdGhldGFfMSBcdmFyZXBzaWxvbl97dC0xfSAtIFx0aGV0YV8yIFx2YXJlcHNpbG9uX3t0LTJ9IC0gXGxkb3RzIC0gXHRoZXRhX3EgXHZhcmVwc2lsb25fe3QtcX0gXFwgJCQKCgpJbnRlZ3JhdGVkIChJKSB0ZXJtIChkKSByZWZlcnMgdG8gZGlmZmVyZW5jaW5nIHRoZSB0aW1lIHNlcmllcyBkYXRhIHRvIG1ha2UgaXQgc3RhdGlvbmFyeS4gU3RhdGlvbmFyaXR5IGlzIG9mdGVuIHJlcXVpcmVkIGZvciB0aW1lIHNlcmllcyBhbmFseXNpcywgYW5kIHRoZSBvcmRlciBvZiBkaWZmZXJlbmNpbmcgaXMgcmVwcmVzZW50ZWQgYnkgdGhlICJkIiBwYXJhbWV0ZXIuIAoKVGhlIEFSSU1BIGVxdWF0aW9uIDogCgokJCB5X3QgPSBcbXUgKyBccGhpXzEgeV97dC0xfSArIFxwaGlfMiB5X3t0LTJ9ICsgXGxkb3RzICsgXHBoaV9wIHlfe3QtcH0gKyBcZXBzaWxvbl90IC0gXHRoZXRhXzEgXGVwc2lsb25fe3QtMX0gLSBcdGhldGFfMiBcZXBzaWxvbl97dC0yfSAtIFxsZG90cyAtIFx0aGV0YV9xIFxlcHNpbG9uX3t0LXF9IFxcIAokJCAkJCAKXGJlZ2lue2FsaWduKn0KXHRleHR7V2hlcmV9OlxcCiZ5X3QgXHRleHR7IGlzIHRoZSBvYnNlcnZlZCB0aW1lIHNlcmllcyBhdCB0aW1lIH0gdCwgXFwKJlxtdSBcdGV4dHsgaXMgdGhlIG1lYW4gb2YgdGhlIHRpbWUgc2VyaWVzLH0gXFwKJlxlcHNpbG9uX3QgXHRleHR7IGlzIHRoZSB3aGl0ZSBub2lzZSBlcnJvciB0ZXJtIGF0IHRpbWUgfSB0LCBcXAomXHBoaV8xLCBccGhpXzIsIFxsZG90cywgXHBoaV9wIFx0ZXh0eyBhcmUgdGhlIGF1dG9yZWdyZXNzaXZlIChBUikgY29lZmZpY2llbnRzfSwgXFwKJnAgXHRleHR7IGlzIHRoZSBvcmRlciBvZiB0aGUgYXV0b3JlZ3Jlc3NpdmUgcGFydCx9IFxcCiZcdGhldGFfMSwgXHRoZXRhXzIsIFxsZG90cywgXHRoZXRhX3EgXHRleHR7IGFyZSB0aGUgbW92aW5nIGF2ZXJhZ2UgKE1BKSBjb2VmZmljaWVudHMsfSBcXAomcSBcdGV4dHsgaXMgdGhlIG9yZGVyIG9mIHRoZSBtb3ZpbmcgYXZlcmFnZSBwYXJ0Ln0KXGVuZHthbGlnbip9ClwKJCQKClRoZSAqKmF1dG8uYXJpbWEqKiBpcyBhIGZ1bmN0aW9uIGluIFIgKHBhcnQgb2YgdGhlIGZvcmVjYXN0IHBhY2thZ2UpIHRoYXQgYXV0b21hdGVzIHRoZSBzZWxlY3Rpb24gb2YgdGhlIGJlc3QgQVJJTUEgbW9kZWwgZm9yIGEgZ2l2ZW4gdGltZSBzZXJpZXMuIEZvciB0aGlzIHRpbWUgc2VyaXNlIGFuYWx5c2lzLCBJIHdpbGwgdXRpbGl6ZSB0aGUgYXV0by5hcmltYSAgc3VnZ2VzdGVkIG1vZGVscyBmb3IgZWFjaCBEcnkgRm9vZHMgYW5kIFdldCBGb29kcyBzY2VuYXJpby4gVGhlIGZ1bmN0aW9uIHdpbGwgY29uZHVjdCBhIHNlYXJjaCBvdmVyIHBvc3NpYmxlIGNvbWJpbmF0aW9ucyBvZiBwLCBkLCBhbmQgcSBhbmQgc2VsZWN0cyB0aGUgbW9kZWwgd2l0aCB0aGUgbG93ZXN0IEFJQywgQklDIG9yIG90aGVyIGNyaXRlcmlhLiBUaGUgZ29hbCBpcyB0byBmaW5kIHRoZSBtb3N0IHN1aXRhYmxlIEFSSU1BIG1vZGVsIHdpdGhvdXQgdGhlIG5lZWQgZm9yIG1hbnVhbCB0cmlhbC1hbmQtZXJyb3IuCgoKIyMjIERyeSBGb29kcyBEYXRhOiBhdXRvLmFyaW1hIHN1Z2dlc3RlZCBtb2RlbAoKYGBge3IsZmlnLndpZHRoPTcsZmlnLmhlaWdodD0xMCxlY2hvPUZBTFNFfQoKZHJ5Zm9vZF9tb2RlbDwtYXV0by5hcmltYShkcnlmb29kKQpwcmludChkcnlmb29kX21vZGVsKQoKYGBgCgpUaGUgQVJJTUEoMCwwLDApKDAsMCwyKVsxMl0gbW9kZWwgd2l0aCBhIG5vbi16ZXJvIG1lYW4gaGFzIHRoZSBmb2xsb3dpbmcgZXF1YXRpb246CgokJCBcYmVnaW57YWxpZ24qfQp5X3QgJj0gMy4zNTkxIC0gMC4xNjQ0IFx2YXJlcHNpbG9uX3t0LTF9IC0gMC4xNjYwIFx2YXJlcHNpbG9uX3t0LTJ9ICsgXHZhcmVwc2lsb25fdCBcXApcZW5ke2FsaWduKn0KJCQKJCQgXGJlZ2lue2FsaWduKn0KXHRleHR7V2hlcmU6fVxcClx0ZXh0e3NtYTF9ICY9IC0wLjE2NDQgXHF1YWQgXHRleHR7KENvZWZmaWNpZW50IGZvciB0aGUgZmlyc3QgbW92aW5nIGF2ZXJhZ2UgdGVybSl9IFxcClx0ZXh0e3NtYTJ9ICY9IC0wLjE2NjAgXHF1YWQgXHRleHR7KENvZWZmaWNpZW50IGZvciB0aGUgc2Vjb25kIG1vdmluZyBhdmVyYWdlIHRlcm0pfSBcXApcdGV4dHttZWFufSAmPSAzLjM1OTEgXHF1YWQgXHRleHR7KE5vbi16ZXJvIG1lYW4gdGVybSl9IFxcClxzaWdtYV4yICY9IDAuNTY1MSBccXVhZCBcdGV4dHsoVmFyaWFuY2Ugb2YgdGhlIHdoaXRlIG5vaXNlIGVycm9yIHRlcm0pfSBcXApcdGV4dHtMb2cgbGlrZWxpaG9vZH0gJj0gLTE2OS4wOSBccXVhZCBcdGV4dHsoTG9nLWxpa2VsaWhvb2QgdmFsdWUpfSBcXApcdGV4dHtBSUN9ICY9IDM0Ni4xNyBccXVhZCBcdGV4dHsoQWthaWtlIEluZm9ybWF0aW9uIENyaXRlcmlvbil9IFxcClx0ZXh0e0FJQ2N9ICY9IDM0Ni40NSBccXVhZCBcdGV4dHsoQ29ycmVjdGVkIEFJQyl9IFxcClx0ZXh0e0JJQ30gJj0gMzU4LjIyIFxxdWFkIFx0ZXh0eyhCYXllc2lhbiBJbmZvcm1hdGlvbiBDcml0ZXJpb24pfQpcZW5ke2FsaWduKn0KJCQKXG5ld3BhZ2UKCiMgRGlhZ25vc3RpYyBDaGVja2luZwoKIyMjIFNBUklNQSBNb2RlbAoKVGhlIFNlYXNvbmFsIEF1dG9yZWdyZXNzaXZlIEludGVncmF0ZWQgTW92aW5nIEF2ZXJhZ2UgKlNBUklNQSogIGlzIGFuIGV4dGVuc2lvbiBvZiB0aGUgQVJJTUEgbW9kZWwsIHNwZWNpZmljYWxseSBkZXNpZ25lZCB0byBoYW5kbGUgdGltZSBzZXJpZXMgZGF0YSB3aXRoIGEgc2Vhc29uYWwgY29tcG9uZW50LiBUaGlzIGJlY29tZXMgY3J1Y2lhbCB3aGVuIHRoZSB0aW1lIHNlcmllcyBleGhpYml0cyByZXBlYXRpbmcgcGF0dGVybnMgYXQgZml4ZWQgaW50ZXJ2YWxzLCBzdWNoIGFzIGRhaWx5LCBtb250aGx5LCBvciB5ZWFybHkgc2Vhc29uYWxpdHkuIEluIFNBUklNQSB0aGUgJ1MnIHN0YW5kcyBmb3IgU2Vhc29uYWwsIGFuZCB0aGUgbW9kZWwgYWNjb3VudHMgZm9yIHBlcmlvZGljIHBhdHRlcm5zIG9yIHRyZW5kcyBpbiB0aGUgZGF0YS4gQSBTQVJJTUEgbW9kZWwgaXMgZGVub3RlZCBhcyBTQVJJTUEocCwgZCwgcSkoUCwgRCwgUSlbc10sIHdoZXJlOgoKcCwgZCwgcTogTm9uLXNlYXNvbmFsIEFSSU1BIGNvbXBvbmVudHMuClAsIEQsIFE6IFNlYXNvbmFsIEFSSU1BIGNvbXBvbmVudHMuCnM6IFNlYXNvbmFsIHBlcmlvZC4KCkluIHRoaXMgYW5hbHlzaXMsIEkgd2lsbCBlbXBsb3kgdGhlIFNlYXNvbmFsIEF1dG9yZWdyZXNzaXZlIEludGVncmF0ZWQgTW92aW5nIEF2ZXJhZ2UgKFNBUklNQSkgbW9kZWwgZm9yIHJlc2lkdWFsIGFuYWx5c2lzLgoKCiMjIyBEcnkgRm9vZHMgUmVzaWR1YWwgQ2hlY2tpbmcgCmBgYHtyLGZpZy53aWR0aD03LGZpZy5oZWlnaHQ9OCxlY2hvPUZBTFNFLHJlc3VsdHM9J2hpZGUnfQoKI3M8LSBzYXJpbWEoZGlmZl9kcnlmb29kLHA9MCxkPTAscT0xLFA9MCxEPTAsUT0xLFMgPSAxMikKczwtIHNhcmltYShkcnlmb29kLHA9MCxkPTAscT0wLFA9MCxEPTAsUT0yLFMgPSAxMikKCiNzPC1zYXJpbWEoZGlmZl9kcnlmb29kLDAsMCwxKQpgYGAKCgpGb3IgdGhlIERyeSBGb29kIGRhdGEgdGhlIGF1dG8uYXJpbWEgZnVuY3Rpb24gcmVjb21tZW5kZWQgQVJJTUEoMCwwLDApICgwLDAsMikgWzEyXSB0byBtb2RlbCB0aGUgcmVncmVzc2lvbiBlcnJvcnMuIENvZWZmaWNpZW50cyBhcmUgYXMgaW5kaWNhdGVkIGFib3ZlLiBUaGUgcmVzaWR1YWxzIG9mIHRoZSBtb2RlbCBhcHBlYXIgc2F0aXNmYWN0b3J5LiBOb3RpY2U6IGh5cG90aGVzaXMgdGVzdGluZyBvZiB0aGUgc2lnbmlmaWNhbmNlIG9mIHRoZSBjb2VmZmljaWVudHMgd2FzIHBlcmZvcm1lZCB1c2luZyB0aGUgc2FyaW1hIGZ1bmN0aW9uLiBUaGUgcC12YWx1ZXMgb2YgdGhlIExqdW5nLUJveCB0ZXN0IGFyZSBhbGwgYWJvdmUgemVybyBhbmQgYWJvdmUgdGhlIGdyaWRlIGxpbmUuClRoZSByZXNpZHVhbCBlcnJvcnMgYXBwZWFyIHRvIGhhdmUgYSBuZWFybHkgdW5pZm9ybSB2YXJpYW5jZSBhbmQgZmx1Y3R1YXRlIGFyb3VuZCBhIG1lYW4gb2YgemVybyAuIEZyb20gdGhlIE5vcm1hbCBRLVEgcGxvdCwgSSBjYW4gc2VlIHRoYXQgSSBhbG1vc3QgaGF2ZSBhIHN0cmFpZ2h0IGxpbmUsIGluZGljYXRpbmcgdGhlIG5vcm1hbGl0eSBhc3N1bXB0aW9uIGRvZXNu4oCZdCBzZWVtIHRvIGJlIHZpb2xhdGVkLiBUaGUgY29ycmVsb2dyYW0sIGFsc28ga25vd24gYXMgdGhlIEFDRidzIGFyZSBhbGwgd2l0aGluIHRoZSBzaWduaWZpY2FuY2UgbGV2ZWwsIHN1Z2dlc3RzIHRoYXQgdGhlcmUgaXMgbm8gYXV0b2NvcnJlbGF0aW9uIGluIHRoZSByZXNpZHVhbHMuIE92ZXJhbGwsIHRoZSBmaXR0ZWQgbW9kZWwgbG9va3MgZ29vZC4KCiMjIFdldCBGb29kcyBEYXRhOiBhdXRvLmFyaW1hIHN1Z2dlc3RlZCBtb2RlbCAKYGBge3IsZmlnLndpZHRoPTcsZmlnLmhlaWdodD04LGVjaG89RkFMU0V9Cgp3ZXRmb29kX21vZGVsPC1hdXRvLmFyaW1hKHdldGZvb2QpCnByaW50KHdldGZvb2RfbW9kZWwpCgpgYGAKVGhlIEFSSU1BKDIsMCwyKSgyLDAsMClbMTJdIHN1Z2dlc3RlZCBtb2RlbCBmb3Igd2V0IGZvb2QgZGF0YSBjYW4gYmUgcmVwcmVzZW50ZWQgYXMgZm9sbG93czoKCiQkIFxiZWdpbnthbGlnbip9CnlfdCA9IC0xLjMwNDR5X3t0LTF9IC0gMC4zNzUzeV97dC0yfSArIDEuMTAzNFx2YXJlcHNpbG9uX3t0LTF9ICsgMC4xNDg4XHZhcmVwc2lsb25fe3QtMn0gKyAwLjAyMDhcYWxwaGFfe3QtMTJ9IC0gMC4wNDY4XGJldGFfe3QtMTJ9XjIgKyAyLjgzMjAgKyBcdmFyZXBzaWxvbl90IFxcClx0ZXh0YmZ7Q29lZmZpY2llbnRzOn0KXGJlZ2lue2FycmF5fXtjY2NjY2NjfQomIGFyMSAmIGFyMiAmIG1hMSAmIG1hMiAmIHNhcjEgJiBzYXIyICYgbWVhbiBcXApcdGV4dHtWYWx1ZX0gJiAtMS4zMDQ0ICYgLTAuMzc1MyAmIDEuMTAzNCAmIDAuMTQ4OCAmIDAuMDIwOCAmIC0wLjA0NjggJiAyLjgzMjAgXFwKXHRleHR7U3RhbmRhcmQgRXJyb3J9ICYgMC4zMTI4ICYgMC4zMDE5ICYgMC4zMjg0ICYgMC4zMTg1ICYgMC4wOTE0ICYgMC4xMDE4ICYgMC4wNDY3IFxcClxlbmR7YXJyYXl9ClxlbmR7YWxpZ24qfQokJAojIyBXZXQgRm9vZHMgUmVzaWR1YWwgQ2hlY2tpbmcKCkZvciB0aGUgV2V0IEZvb2RzIGRhdGEsIGF1dG8uYXJpbWEgZnVuY3Rpb24gcmVjb21tZW5kZWQgdGhlIEFSSU1BKDIsMCwyKSgyLDAsMClbMTJdIG1vZGVsLiBUaGUgY29lZmZpY2llbnRzIGFyZSBhcyBpbmRpY2F0ZWQgYmVsb3cgdXNpbmcgKipTQVJJTUEqKiBtb2RlbC4KCmBgYHtyLGZpZy53aWR0aD03LGZpZy5oZWlnaHQ9OCxlY2hvPUZBTFNFLHJlc3VsdHM9J2hpZGUnfQoKczE8LXNhcmltYSh3ZXRmb29kLHA9MixkPTAscT0yLFA9MixEPTAsUT0wLFMgPSAxMikKI3MxIDwtIHNhcmltYSh3ZXRmb29kLDAsMCwxKQoKYGBgCgpUaGUgcmVzaWR1YWxzIG9mIHRoZSBtb2RlbCBhcHBlYXIgc2F0aXNmYWN0b3J5LiBJdCdzIGltcG9ydGFudCB0byBub3RlIHRoYXQgaHlwb3RoZXNpcyB0ZXN0aW5nIG9mIHRoZSBzaWduaWZpY2FuY2Ugb2YgdGhlIGNvZWZmaWNpZW50cyB3YXMgcGVyZm9ybWVkIHVzaW5nIHRoZSBzYXJpbWEgZnVuY3Rpb24uIFRoZSBwLXZhbHVlcyBvZiB0aGUgTGp1bmctQm94IHRlc3QgYXJlIGFsbCBhYm92ZSB6ZXJvIGFuZCBhYm92ZSB0aGUgc2lnbmlmaWNhbmNlIGxldmVsLCBpbmRpY2F0aW5nIG5vIHNpZ25pZmljYW50IGF1dG9jb3JyZWxhdGlvbiBpbiB0aGUgcmVzaWR1YWxzLgoKTW9yZW92ZXIsIHRoZSByZXNpZHVhbCBlcnJvcnMgZXhoaWJpdCBhIG5lYXJseSB1bmlmb3JtIHZhcmlhbmNlIGFuZCBmbHVjdHVhdGUgYXJvdW5kIGEgbWVhbiBvZiB6ZXJvLiBUaGUgTm9ybWFsIFEtUSBwbG90IHNob3dzIGEgbmVhcmx5IHN0cmFpZ2h0IGxpbmUsIHN1Z2dlc3RpbmcgdGhhdCB0aGUgbm9ybWFsaXR5IGFzc3VtcHRpb24gaXMgbm90IHZpb2xhdGVkLiBBZGRpdGlvbmFsbHksIHRoZSBjb3JyZWxvZ3JhbSAoQUNGKSBwbG90cyBhcmUgYWxsIHdpdGhpbiB0aGUgc2lnbmlmaWNhbmNlIGxldmVsLCBpbmRpY2F0aW5nIG5vIGF1dG9jb3JyZWxhdGlvbiBpbiB0aGUgcmVzaWR1YWxzLgoKSW4gc3VtbWFyeSwgYmFzZWQgb24gdmFyaW91cyBkaWFnbm9zdGljIGNoZWNrcywgdGhlIGZpdHRlZCBtb2RlbCBhcHBlYXJzIHRvIGJlIHdlbGwtc3VpdGVkIGZvciB0aGUgV2V0IEZvb2RzIGRhdGEsIGFuZCB0aGUgb3ZlcmFsbCBnb29kbmVzcy1vZi1maXQgaXMgc2F0aXNmYWN0b3J5LgoKCiMjIENvZWZmaWNpZW50cyBTdW1tYXJ5CgpgYGB7cixlY2hvPUZBTFNFfQpwYXIobWZyb3c9YygzLDEpKQprYWJsZShzJHR0YWJsZSxjYXB0aW9uID0gIkRyeSBGb29kcyBDb2VmZmljaWVudCBTdW1tYXJ5IikKa2FibGUoczEkdHRhYmxlLGNhcHRpb24gPSAiV2V0IEZvb2RzIENvZWZmaWNpZW50IFN1bW1hcnkiKQpgYGAKRnJvbSB0aGUgRHJ5IEZvb2RzIGNvZWZmaWNpZW50IHN1bW1hcnksICpzbWExKiBlc3RpbWF0ZSByZXByZXNlbnRzIHRoZSBlc3RpbWF0ZWQgY29lZmZpY2llbnQgZm9yIHRoZSBmaXJzdCB0ZXJtIGluIHRoZSBTQVJJTUEgbW9kZWwuIFRoZSBuZWdhdGl2ZSBlc3RpbWF0ZSBzdWdnZXN0cyBhbiBpbnZlcnNlIHJlbGF0aW9uc2hpcC4gVGhlIHQudmFsdWUgYW5kIHAudmFsdWUgcHJvdmlkZSBpbmZvcm1hdGlvbiBhYm91dCB0aGUgc3RhdGlzdGljYWwgc2lnbmlmaWNhbmNlIG9mIHRoaXMgY29lZmZpY2llbnQuIEluIHRoaXMgY2FzZSwgdGhlIHAudmFsdWUgaXMgZ3JlYXRlciB0aGFuIHRoZSBjb21tb24gc2lnbmlmaWNhbmNlIGxldmVsIG9mIDAuMDUsIGluZGljYXRpbmcgdGhhdCB0aGUgY29lZmZpY2llbnQgbWlnaHQgbm90IGJlIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQuCgpTaW1pbGFyIHRvIHNtYTEsIHNtYTIgcmVwcmVzZW50cyB0aGUgZXN0aW1hdGVkIGNvZWZmaWNpZW50IGZvciB0aGUgc2Vjb25kIHRlcm0gaW4gdGhlIFNlYXNvbmFsIEF1dG9yZWdyZXNzaXZlIEludGVncmF0ZWQgTW92aW5nIEF2ZXJhZ2UgbW9kZWwuIFRoZSBuZWdhdGl2ZSBlc3RpbWF0ZSBpbXBsaWVzIGFuIGludmVyc2UgcmVsYXRpb25zaGlwLiBUaGUgdC52YWx1ZSBhbmQgcC52YWx1ZSBzdWdnZXN0IHRoYXQsIHNpbWlsYXIgdG8gc21hMSwgdGhpcyBjb2VmZmljaWVudCBtaWdodCBub3QgYmUgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudC4KClRoZSAqeG1lYW4qIHJlcHJlc2VudHMgdGhlIG1lYW4gdGVybS4gVGhlIGVzdGltYXRlIGluZGljYXRlcyB0aGUgZXN0aW1hdGVkIG1lYW4gdmFsdWUsIHRoZSBlc3RpbWF0ZSBpcyAzLjM1OTEsIHRoZSBzdGFuZGFyZCBlcnJvciBpcyAwLjA0MzgsIHRoZSB0LXZhbHVlIGlzIDc2LjY1OTQsIGFuZCB0aGUgcC12YWx1ZSBpcyAgemVyby4gVGhlIGhpZ2ggdC52YWx1ZSBhbmQgdmVyeSBsb3cgcC52YWx1ZSAgc3VnZ2VzdCB0aGF0IHRoZSBtZWFuIHRlcm0gaXMgaGlnaGx5IHNpZ25pZmljYW50LCBhbmQgdGhlIG1vZGVsIGhlYXZpbHkgcmVsaWVzIG9uIHRoaXMgdGVybS4gVGhlIGxvdyBwLnZhbHVlIGluZGljYXRlcyBhIGhpZ2ggbGV2ZWwgb2Ygc3RhdGlzdGljYWwgc2lnbmlmaWNhbmNlLiBUaGlzIHN1Z2dlc3RzIHRoYXQgdGhlICJ4bWVhbiIgY29lZmZpY2llbnQgaXMgaGlnaGx5IHNpZ25pZmljYW50IGluIHRoZSBEcnkgRm9vZHMgbW9kZWwuCgpJbiB0aGUgY29lZmZpY2llbnQgc3VtbWFyeSBmb3IgdGhlIFdldCBGb29kcyBtb2RlbCwgKmFyMSogKEF1dG9SZWdyZXNzaXZlIHRlcm0gMSkgZXN0aW1hdGUgcmVwcmVzZW50cyB0aGUgZXN0aW1hdGVkIGNvZWZmaWNpZW50IGZvciB0aGUgZmlyc3QgdGVybSBpbiB0aGUgQVJJTUEgbW9kZWwudGhlIG5lZ2F0aXZlIGVzdGltYXRlIHN1Z2dlc3RzIGEgbmVnYXRpdmUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIGN1cnJlbnQgdmFsdWUgYW5kIGl0cyBwcmV2aW91cyB2YWx1ZS4gVGhlIHQudmFsdWUgaXMgcmVsYXRpdmVseSBsYXJnZSwgYW5kIHRoZSBsb3cgcC52YWx1ZSBpbmRpY2F0ZXMgdGhhdCB0aGlzIGNvZWZmaWNpZW50IGlzIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQuIFNpbWlsYXIgdG8gYXIxLCBhcjIgcmVwcmVzZW50cyB0aGUgcmVsYXRpb25zaGlwIHdpdGggdGhlIHZhbHVlIHR3byB0aW1lIHBvaW50cyBhZ28uIFRoZSBlc3RpbWF0ZSBpcyBuZWdhdGl2ZSwgYnV0IHRoZSBwLnZhbHVlIGlzIHJlbGF0aXZlbHkgaGlnaCwgc3VnZ2VzdGluZyB0aGF0IHRoaXMgY29lZmZpY2llbnQgbWlnaHQgbm90IGJlIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQuCgoqbWExKiAoTW92aW5nIEF2ZXJhZ2UgdGVybSAxKSB0aGUgcG9zaXRpdmUgZXN0aW1hdGUgc3VnZ2VzdHMgYSBwb3NpdGl2ZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgY3VycmVudCB2YWx1ZSBhbmQgdGhlIHJlc2lkdWFsIGZyb20gdGhlIHByZXZpb3VzIHBlcmlvZC4gVGhlIHQudmFsdWUgaXMgbGFyZ2UsIGFuZCB0aGUgbG93IHAudmFsdWUgaW5kaWNhdGVzIHN0YXRpc3RpY2FsIHNpZ25pZmljYW5jZS4gU2ltaWxhciB0byBtYTEsIG1hMiByZXByZXNlbnRzIHRoZSByZWxhdGlvbnNoaXAgd2l0aCB0aGUgcmVzaWR1YWwgdHdvIHBlcmlvZHMgYWdvLiBUaGUgZXN0aW1hdGUgaXMgcG9zaXRpdmUsIGJ1dCB0aGUgcC52YWx1ZSBpcyBoaWdoLCBpbmRpY2F0aW5nIHRoYXQgdGhpcyBjb2VmZmljaWVudCBtaWdodCBub3QgYmUgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudC4KCipzYXIxKiAoU2Vhc29uYWwgQXV0b1JlZ3Jlc3NpdmUgdGVybSAxKSwgIHRoZSBlc3RpbWF0ZSBpcyBjbG9zZSB0byB6ZXJvLCBhbmQgdGhlIGhpZ2ggcC52YWx1ZSBzdWdnZXN0cyB0aGF0IHRoaXMgc2Vhc29uYWwgQXV0b1JlZ3Jlc3NpdmUgdGVybSBtaWdodCBub3QgYmUgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudC4gU2ltaWxhciB0byBzYXIxLCBzYXIyIHJlcHJlc2VudHMgYSBzZWFzb25hbCByZWxhdGlvbnNoaXAuIFRoZSBlc3RpbWF0ZSBpcyBuZWdhdGl2ZSwgYnV0IHRoZSBwLnZhbHVlIGlzIGhpZ2gsIGluZGljYXRpbmcgcG90ZW50aWFsIGluc2lnbmlmaWNhbmNlLiAKCip4bWVhbiogdGhlIGVzdGltYXRlIHJlcHJlc2VudHMgdGhlIG1lYW4gdGVybS4gVGhlIGhpZ2ggdC52YWx1ZSBhbmQgdmVyeSBsb3cgcC52YWx1ZSBpbmRpY2F0ZSB0aGF0IHRoZSBtZWFuIHRlcm0gaXMgaGlnaGx5IHNpZ25pZmljYW50IGluIHRoaXMgbW9kZWwuCgoKIyMgQXNzZXNzbWVudCBvZiBGaXQKClRoZSAiTW9kZWwgU2NvcmVzIiByZXByZXNlbnQgdGhlIGV2YWx1YXRpb24gbWV0cmljcyBBSUMsIEFJQ2MsIEJJQyBmb3IgdGhlIGZvcmVjYXN0aW5nIG1vZGVsIHVzZWQgZm9yIGVhY2ggY2F0ZWdvcnkgRHJ5IEZvb2RzIGFuZCBXZXQgRm9vZHMuIEFJQyBpcyBhIG1lYXN1cmUgb2YgdGhlIG1vZGVsJ3MgZ29vZG5lc3Mgb2YgZml0LCBiYWxhbmNpbmcgdGhlIGFjY3VyYWN5IG9mIHRoZSBtb2RlbCB3aXRoIGl0cyBjb21wbGV4aXR5LiBMb3dlciBBSUMgdmFsdWVzIGluZGljYXRlIGJldHRlci1maXR0aW5nIG1vZGVscy4gQUlDYyBpcyBhIGNvcnJlY3Rpb24gdG8gQUlDLCBwYXJ0aWN1bGFybHkgdXNlZnVsIGZvciBzbWFsbCBzYW1wbGUgc2l6ZXMuIFNpbWlsYXIgdG8gQUlDLCBsb3dlciBBSUNjIHZhbHVlcyBzdWdnZXN0IGJldHRlci1maXR0aW5nIG1vZGVscy4gQklDIGlzIGFub3RoZXIgY3JpdGVyaW9uIGZvciBtb2RlbCBzZWxlY3Rpb24gdGhhdCBwZW5hbGl6ZXMgY29tcGxleGl0eS4gTGlrZSBBSUMsIGxvd2VyIEJJQyB2YWx1ZXMgaW5kaWNhdGUgbW9kZWxzIHRoYXQgYmFsYW5jZSBhY2N1cmFjeSBhbmQgc2ltcGxpY2l0eS4gCgpgYGB7cixlY2hvPUZBTFNFfQoKa2FibGUoZGF0YS5mcmFtZShNb2RlbCA9IGMoIkRyeSBGb29kcyIsICJXZXQgRm9vZHMiKSwKICAgICAgICAgICAgICAgICBBSUMgPSBjKGRyeWZvb2RfbW9kZWwkYWljLHdldGZvb2RfbW9kZWwkYWljKSwKICAgICAgICAgICAgICAgICBBSUNjID0gYyhkcnlmb29kX21vZGVsJGFpY2Msd2V0Zm9vZF9tb2RlbCRhaWNjKSwKICAgICAgICAgICAgICAgICBCSUMgPSBjKGRyeWZvb2RfbW9kZWwkYmljLHdldGZvb2RfbW9kZWwkYmljKSksCiAgICAgIGNhcHRpb24gPSAnTW9kZWwgU2NvcmVzJykKCgpgYGAKVGhlIFdldCBGb29kcyBtb2RlbCBnZW5lcmFsbHkgaGFzIGxvd2VyIHZhbHVlcyBhY3Jvc3MgYWxsIHRocmVlIG1ldHJpY3MgKEFJQywgQUlDYywgQklDKSwgc3VnZ2VzdGluZyB0aGF0IGl0IG1heSBiZSBhIGJldHRlci1maXR0aW5nIGFuZCBsZXNzIGNvbXBsZXggbW9kZWwgY29tcGFyZWQgdG8gdGhlIERyeSBGb29kcyBtb2RlbC4KCgojIyBNb2RlbCBBY2N1cmFjeQoKYGBge3IsZWNobz1GQUxTRX0KIyBBc3N1bWluZyBkcnlmb29kX21vZGVsIGFuZCB3ZXRmb29kX21vZGVsIGFyZSB5b3VyIGZvcmVjYXN0aW5nIG1vZGVscwpkcnlmb29kX2FjY3VyYWN5IDwtIGFjY3VyYWN5KGRyeWZvb2RfbW9kZWwgJT4lIGZvcmVjYXN0KGggPSAxMikpCndldGZvb2RfYWNjdXJhY3kgPC0gYWNjdXJhY3kod2V0Zm9vZF9tb2RlbCAlPiUgZm9yZWNhc3QoaCA9IDEyKSkKCiMgQ3JlYXRlIGEgZGF0YSBmcmFtZSBmb3IgYWNjdXJhY3kgbWV0cmljcwphY2N1cmFjeV9kZiA8LSBkYXRhLmZyYW1lKAogIE1vZGVsID0gYygiRHJ5IEZvb2RzIiwgIldldCBGb29kcyIpLAogIE1FID0gYyhkcnlmb29kX2FjY3VyYWN5WzFdLCB3ZXRmb29kX2FjY3VyYWN5WzFdKSwKICBSTVNFID0gYyhkcnlmb29kX2FjY3VyYWN5WzJdLCB3ZXRmb29kX2FjY3VyYWN5WzJdKSwKICBNQUUgPSBjKGRyeWZvb2RfYWNjdXJhY3lbM10sIHdldGZvb2RfYWNjdXJhY3lbM10pLAogIE1QRSA9IGMoZHJ5Zm9vZF9hY2N1cmFjeVs0XSwgd2V0Zm9vZF9hY2N1cmFjeVs0XSksCiAgTUFQRSA9IGMoZHJ5Zm9vZF9hY2N1cmFjeVs1XSwgd2V0Zm9vZF9hY2N1cmFjeVs1XSksCiAgTUFTRSA9IGMoZHJ5Zm9vZF9hY2N1cmFjeVs2XSwgd2V0Zm9vZF9hY2N1cmFjeVs2XSksCiAgQUNGMSA9IGMoZHJ5Zm9vZF9hY2N1cmFjeVs3XSwgd2V0Zm9vZF9hY2N1cmFjeVs3XSkKKQoKIyBQcmludCB0aGUgYWNjdXJhY3kgZGF0YSBmcmFtZQojcHJpbnQoYWNjdXJhY3lfZGYpCmBgYAoKCmBgYHtyLGVjaG89RkFMU0V9CmxpYnJhcnkoa25pdHIpCgojIENyZWF0ZSBhIGthYmxlIHRhYmxlCmthYmxlKAogIGFjY3VyYWN5X2RmLAogIGNhcHRpb24gPSAiKipNb2RlbCBBY2N1cmFjeSoqIiwKICBmb3JtYXQgPSAibWFya2Rvd24iLAogIGNvbC5uYW1lcyA9IGMoIk1vZGVsIiwgIk1FIiwgIlJNU0UiLCAiTUFFIiwgIk1QRSIsICJNQVBFIiwgIk1BU0UiLCAiQUNGMSIpCikKYGBgCgpUaGUgYWNjdXJhY3kgbWV0cmljcyBmb3IgdGhlIGZvcmVjYXN0aW5nIG1vZGVscyBvbiBib3RoIERyeSBGb29kcyBhbmQgV2V0IEZvb2RzIGluZGljYXRlIGEgcmVhc29uYWJseSBlZmZlY3RpdmUgcGVyZm9ybWFuY2Ugd2l0aCBzb21lIGNvbnNpZGVyYXRpb25zLgoKTWVhbiBFcnJvcjogVGhlIG1vZGVsIHRlbmRzIHRvIHNsaWdodGx5IHVuZGVyZXN0aW1hdGUgdGhlIGRlbWFuZCBmb3IgYm90aCBEcnkgRm9vZHMgYW5kIFdldCBGb29kcyBvbiBhdmVyYWdlLCB3aGljaCBtYXkgbmVlZCBmdXJ0aGVyIGludmVzdGlnYXRpb24gdG8gdW5kZXJzdGFuZCB0aGUgYmlhcy4KClJvb3QgTWVhbiBTcXVhcmVkIEVycm9yOiBUaGUgUk1TRSB2YWx1ZXMgYXJlIHJlbGF0aXZlbHkgbG93IGZvciBib3RoIERyeSBGb29kcyBhbmQgV2V0IEZvb2RzLCBzdWdnZXN0aW5nIHRoYXQgdGhlIG1vZGVsJ3MgcHJlZGljdGlvbnMgYXJlIGdlbmVyYWxseSBjbG9zZSB0byB0aGUgb2JzZXJ2ZWQgdmFsdWVzLgoKTWVhbiBBYnNvbHV0ZSBFcnJvcjogVGhlIE1BRSB2YWx1ZXMgYXJlIHJlYXNvbmFibGUsIGluZGljYXRpbmcgdGhhdCB0aGUgbW9kZWwncyBhYnNvbHV0ZSBlcnJvcnMgYXJlIHJlbGF0aXZlbHkgc21hbGwgb24gYXZlcmFnZS4KCk1lYW4gUGVyY2VudGFnZSBFcnJvcjogVGhlIG5lZ2F0aXZlIE1QRSB2YWx1ZXMgaW5kaWNhdGUgYSBjb25zaXN0ZW50IHVuZGVyZXN0aW1hdGlvbiBvZiBkZW1hbmQuIEl0J3MgY3J1Y2lhbCB0byB1bmRlcnN0YW5kIHdoZXRoZXIgdGhpcyBiaWFzIGlzIGFjY2VwdGFibGUgZm9yIHRoZSBhcHBsaWNhdGlvbi4KCk1lYW4gQWJzb2x1dGUgUGVyY2VudGFnZSBFcnJvcjogVGhlIE1BUEUgdmFsdWVzLCB3aGlsZSBub3QgZXh0cmVtZWx5IGhpZ2gsIHN1Z2dlc3QgdGhhdCB0aGUgbW9kZWwncyBwZXJjZW50YWdlIGVycm9ycyBhcmUgbm90YWJsZS4gCgpNZWFuIEFic29sdXRlIFNjYWxlZCBFcnJvcjogQm90aCBNQVNFIHZhbHVlcyBhcmUgYmVsb3cgMSwgaW5kaWNhdGluZyB0aGF0IHRoZSBtb2RlbCBvdXRwZXJmb3JtcyBhIG5haXZlIGZvcmVjYXN0LCBidXQgdGhlcmUgaXMgcm9vbSBmb3IgaW1wcm92ZW1lbnQuCgpUaGUgKk1BUEUqIHZhbHVlcyBmb3IgYm90aCBtb2RlbHMgaW5kaWNhdGUgZmF2b3JhYmxlIGFjY3VyYWN5LCB0cmFuc2xhdGluZyB0byBhbiBlZmZlY3RpdmUgcHJlZGljdGlvbiAqYWNjdXJhY3kgb2YgYXBwcm94aW1hdGVseSA3Ny44JSogZm9yIERyeSBGb29kcyBhbmQgKjc1LjclKiBmb3IgV2V0IEZvb2RzIHdoZW4gc3VidHJhY3RlZCBmcm9tIDEwMCUuIFRoaXMgaW1wbGllcyB0aGF0IHRoZSBtb2RlbHMnIGZvcmVjYXN0cyBhcmUsIG9uIGF2ZXJhZ2UsIHdpdGhpbiBhIDIyLjIwJSBtYXJnaW4gb2YgZXJyb3IgZm9yIERyeSBGb29kcyBhbmQgYSAyNC4zMCUgbWFyZ2luIGZvciBXZXQgRm9vZHMsIHByb3ZpZGluZyBhIHNvbGlkIGJhc2lzIGZvciByZWxpYWJsZSBwcmVkaWN0aW9ucyBpbiB0aGUgY29udGV4dCBvZiBwZXQgZm9vZCBkZW1hbmQgZm9yZWNhc3RpbmcuT3ZlcmFsbCwgYm90aCBtb2RlbHMgc2VlbSB0byBwcm92aWRlIHJlYXNvbmFibGUgZm9yZWNhc3RzLCB3aXRoIHJlbGF0aXZlbHkgbG93IFJNU0UsIE1BRSwgYW5kIE1QRSB2YWx1ZXMuIFRoZSBhdXRvY29ycmVsYXRpb24gYXQgbGFnIDEgKEFDRjEpIGlzIGNsb3NlIHRvIHplcm8sIGluZGljYXRpbmcgdGhhdCB0aGUgbW9kZWxzIGhhdmUgY2FwdHVyZWQgdGhlIHRlbXBvcmFsIHBhdHRlcm5zIHdlbGwuCgoKCiMgUHJlZGljdGlvbiBQZXJmb3JtYW5jZQojIyBGb3JlY2FzdGluZwoKRnJvbSB0aGUgZGF0YXNldCAyMDIyIHRvIDIwMjMgd2FzIHJlc2VydmVkIHNwZWNpZmljYWxseSBmb3IgZXZhbHVhdGluZyB0aGUgcHJlZGljdGl2ZSBwZXJmb3JtYW5jZSBvZiBlYWNoIG1vZGVsIGJ5IGFzc2Vzc2luZyB0aGVpciBhY2N1cmFjeS4gVXRpbGl6aW5nIHRoZSBmb3JlY2FzdCBmdW5jdGlvbiBmcm9tIHRoZSBmb3JlY2FzdCBwYWNrYWdlLCB0aGUgbW9kZWxzIGdlbmVyYXRlZCBwcmVkaWN0aW9ucyBmb3IgdGhlIG5leHQgMTIgbW9udGhzLCBmb3JlY2FzdGluZyBib3RoIERyeSBGb29kcyBhbmQgV2V0IEZvb2RzIGRlbWFuZC4KCmBgYHtyLGZpZy53aWR0aD02LjUsZmlnLmhlaWdodD0zLjUscmVzdWx0cz0naGlkZScsZmlnLnNob3c9J2hvbGQnLGVjaG89RkFMU0V9CgojIEZvcmVjYXN0IGFuZCBwbG90IGRyeSBmb29kCmRyeWZvb2RfbW9kZWwlPiVmb3JlY2FzdChoPTEyKSU+JWF1dG9wbG90KCkrIGF1dG9sYXllcihkcnlmb29kX3Rlc3Qsc2VyaWVzID0gIlRlc3QgRGF0YSIpICsgZ2d0aXRsZSgiRHJ5IEZvb2QgRm9yZWNhc3QgZnJvbSBMb2cgVHJhbnNmb3JtZWQgRGF0YSIpICsgeWxhYigiRHJ5IEZvb2RzIikKCiMgRm9yZWNhc3QgYW5kIHBsb3Qgd2V0IGZvb2QKd2V0Zm9vZF9tb2RlbCU+JWZvcmVjYXN0KGg9MTIpJT4lYXV0b3Bsb3QoKSsKICBhdXRvbGF5ZXIod2V0Zm9vZF90ZXN0LHNlcmllcyA9ICJUZXN0IERhdGEiKSArIGdndGl0bGUoIldldCBGb29kIEZvcmVjYXN0IGZyb20gTG9nIFRyYW5zZm9ybWVkIERhdGEiKSArIAogIHlsYWIoIldldCBGb29kIikKCgoKYGBgCgpFYWNoIGdyYXBoIGluY2x1ZGVzIHRoZSBhY3R1YWwgdGVzdCBkYXRhIGluIG9yYW5nZSwgdGhlIG1lYW4gb2YgdGhlIHByZWRpY3Rpb24gaW4gYmx1ZSwgYW4gODAlIHByZWRpY3Rpb24gaW50ZXJ2YWwgcmVwcmVzZW50ZWQgYnkgYSBkZWVwIHB1cnBsZSBzaGFkZWQgYXJlYSwgYW5kIGEgOTUlIHByZWRpY3Rpb24gaW50ZXJ2YWwgZGlzcGxheWVkIGFzIGEgbGlnaHQgcHVycGxlIHNoYWRlZCBhcmVhLiBUaGVzZSB2aXN1YWxpemF0aW9ucyBwcm92aWRlIGEgY29tcHJlaGVuc2l2ZSBvdmVydmlldyBvZiB0aGUgbW9kZWwncyBmb3JlY2FzdGluZyBjYXBhYmlsaXRpZXMgYW5kIHRoZWlyIGFsaWdubWVudCB3aXRoIHRoZSBhY3R1YWwgdGVzdCBkYXRhLgoKCiMjIEZvcmVjYXN0aW5nIGZyb20gT3JpZ2luYWwgRGF0YQoKTG9nIHRyYW5zZm9ybWF0aW9uIGlzIGEgY29tbW9uIHRlY2huaXF1ZSB1c2VkIGluIHRpbWUgc2VyaWVzIGZvcmVjYXN0aW5nIHRvIHN0YWJpbGl6ZSB2YXJpYW5jZSBhbmQgbWFrZSB0aGUgcGF0dGVybnMgaW4gdGhlIGRhdGEgbW9yZSBhcHBhcmVudC4gV2hlbiB0aGUgbG9nLXRyYW5zZm9ybWVkIHByZWRpY3Rpb25zIGNsb3NlbHkgdHJhY2sgdGhlIG9yaWdpbmFsIGRhdGEsIGl0IHN1Z2dlc3RzIHRoYXQgdGhlIGZvcmVjYXN0aW5nIG1vZGVsIGlzIGNhcHR1cmluZyB0aGUgdW5kZXJseWluZyBwYXR0ZXJucyBlZmZlY3RpdmVseS4gVGhlIGNvbXBhcmlzb24gYmV0d2VlbiB0aGUgYmx1ZSBsb2ctdHJhbnNmb3JtZWQgcHJlZGljdGlvbiBsaW5lIGFuZCB0aGUgb3JhbmdlIG9yaWdpbmFsIGRhdGEgbGluZSBpcyBhIHZpc3VhbCB3YXkgdG8gYXNzZXNzIHRoZSBhY2N1cmFjeSBhbmQgYWxpZ25tZW50IG9mIHRoZSBmb3JlY2FzdGVkIHZhbHVlcyB3aXRoIHRoZSBhY3R1YWwgb2JzZXJ2YXRpb25zCgpgYGB7cixlY2hvPUZBTFNFLGV2YWw9RkFMU0V9CgpwYXIobWZyb3c9YygzLDEpKQoKIyBDcmVhdGUgYSB0aW1lIHNlcmllcyBvYmplY3QgZm9yIERyeSBGb29kcyBmcm9tIHllYXIgb2YgMjAwMQpkcnlmb29kX2RhdGEgPC0gdHMocGV0X2RhdGEkIkRyeSBGb29kcyIsIHN0YXJ0ID0gYygyMDAxLCAxKSwgZW5kID0gYygyMDIzLCAyKSwgZnJlcXVlbmN5ID0gMTIpICAjIEFzc3VtaW5nIG1vbnRobHkgZGF0YSAoZnJlcXVlbmN5PTEyKQoKIyBDcmVhdGUgYSB0aW1lIHNlcmllcyBvYmplY3QgZm9yIFdldCBGb29kcwp3ZXRmb29kX2RhdGEgPC0gdHMocGV0X2RhdGEkIldldCBGb29kcyIsIHN0YXJ0ID0gYygyMDAxLCAxKSwgZW5kID0gYygyMDIzLCAyKSwgZnJlcXVlbmN5ID0gMTIpICAjIEFzc3VtaW5nIG1vbnRobHkgZGF0YSAoZnJlcXVlbmN5PTEyKQoKIyBEcnkgRm9vZHMKIyBDcmVhdGUgYSB0aW1lIHNlcmllcyBvYmplY3QgZm9yIERyeSBGb29kcyBmcm9tIHRoZSB5ZWFyIDIwMTAKI2RyeWZvb2RfZGF0YSA9IGxvZyhkcnlmb29kX2RhdGEpCmRyeWZvb2RfZGF0YSA8LSB0cyhwZXRfZGF0YSQiRHJ5IEZvb2RzIiwgc3RhcnQgPSBjKDIwMTAsIDEpLCBlbmQgPSBjKDIwMjMsIDIpLCBmcmVxdWVuY3kgPSAxMikgICMgQXNzdW1pbmcgbW9udGhseSBkYXRhIChmcmVxdWVuY3k9MTIpCgojIFNldCB0aGUgc3BsaXQgcG9pbnQgKGUuZy4sIDk1JSBmb3IgdHJhaW5pbmcsIDUlIGZvciB0ZXN0aW5nKQpzcGxpdF9wb2ludCA8LSBmbG9vcigwLjk1ICogbGVuZ3RoKGRyeWZvb2RfZGF0YSkpCgojIFNwbGl0IHRoZSBkYXRhIGludG8gdHJhaW5pbmcgYW5kIHRlc3Rpbmcgc2V0cwpkcnlmb29kIDwtIHdpbmRvdyhkcnlmb29kX2RhdGEsIHN0YXJ0ID0gc3RhcnQoZHJ5Zm9vZF9kYXRhKSwgZW5kID0gdGltZShkcnlmb29kX2RhdGEpW3NwbGl0X3BvaW50XSkKCiMgQ3JlYXRlIHRoZSB0ZXN0aW5nIGRhdGEKZHJ5Zm9vZF90ZXN0IDwtIHdpbmRvdyhkcnlmb29kX2RhdGEsIHN0YXJ0ID0gdGltZShkcnlmb29kX2RhdGEpW3NwbGl0X3BvaW50ICsgMV0pCgojIENoZWNrIHRoZSBsZW5ndGhzIG9mIHRyYWluaW5nIGFuZCB0ZXN0aW5nIGRhdGEKbGVuZ3RoKGRyeWZvb2QpCmxlbmd0aChkcnlmb29kX3Rlc3QpCmhlYWQoZHJ5Zm9vZF90ZXN0KQp0YWlsKGRyeWZvb2RfdGVzdCkKCiMgQ3JlYXRlIGEgdGltZSBzZXJpZXMgb2JqZWN0IGZvciBXZXRGb29kcyBmcm9tIHRoZSB5ZWFyIDIwMTAKd2V0Zm9vZF9kYXRhIDwtIHRzKHBldF9kYXRhJCJXZXQgRm9vZHMiLCBzdGFydCA9IGMoMjAxMCwgMSksIGVuZCA9IGMoMjAyMywgMiksIGZyZXF1ZW5jeSA9IDEyKSAgIyBBc3N1bWluZyBtb250aGx5IGRhdGEgKGZyZXF1ZW5jeT0xMikKCiMgU2V0IHRoZSBzcGxpdCBwb2ludCAoZS5nLiwgOTglIGZvciB0cmFpbmluZywgNSUgZm9yIHRlc3RpbmcpCnNwbGl0X3BvaW50IDwtIGZsb29yKDAuOTggKiBsZW5ndGgod2V0Zm9vZF9kYXRhKSkKCiMgU3BsaXQgdGhlIGRhdGEgaW50byB0cmFpbmluZyBhbmQgdGVzdGluZyBzZXRzCndldGZvb2QgPC0gd2luZG93KHdldGZvb2RfZGF0YSwgc3RhcnQgPSBzdGFydCh3ZXRmb29kX2RhdGEpLCBlbmQgPSB0aW1lKHdldGZvb2RfZGF0YSlbc3BsaXRfcG9pbnRdKQoKIyBDcmVhdGUgdGhlIHRlc3RpbmcgZGF0YQp3ZXRmb29kX3Rlc3QgPC0gd2luZG93KHdldGZvb2RfZGF0YSwgc3RhcnQgPSB0aW1lKHdldGZvb2RfZGF0YSlbc3BsaXRfcG9pbnQgKyAxXSkKCiMgQ2hlY2sgdGhlIGxlbmd0aHMgb2YgdHJhaW5pbmcgYW5kIHRlc3RpbmcgZGF0YQojbGVuZ3RoKHRyYWluX2RhdGEpCiNsZW5ndGgodGVzdF9kYXRhKQoKI2hlYWQoZHJ5Zm9vZCkKI3RhaWwoZHJ5Zm9vZCkKYGBgCgpgYGB7cixlY2hvPUZBTFNFLGV2YWw9RkFMU0UscmVzdWx0cz0naGlkZSd9CmRyeWZvb2RfbW9kZWwyPC1hdXRvLmFyaW1hKGRyeWZvb2QpCnByaW50KGRyeWZvb2RfbW9kZWwyKQoKd2V0Zm9vZF9tb2RlbDI8LWF1dG8uYXJpbWEod2V0Zm9vZCkKcHJpbnQod2V0Zm9vZF9tb2RlbDIpCgoKI3MxPC1zYXJpbWEod2V0Zm9vZCxwPTIsZD0wLHE9MixQPTIsRD0wLFE9MCxTID0gMTIpCiNzMSA8LSBzYXJpbWEod2V0Zm9vZCwwLDAsMSkKI3MxPC1zYXJpbWEod2V0Zm9vZCxwPTEsZD0wLHE9MCxQPTEsRD0wLFE9MCxTID0gMTIpCgpgYGAKCmBgYHtyLGZpZy53aWR0aD02LjUsZmlnLmhlaWdodD0zLjUscmVzdWx0cz0naGlkZScsZmlnLnNob3c9J2hvbGQnLGVjaG89RkFMU0V9CiNkcnlmb29kX21vZGVsJT4lZm9yZWNhc3QoaD0xMiklPiVhdXRvcGxvdCgpKwogI2F1dG9sYXllcihkcnlmb29kX3Rlc3Qsc2VyaWVzID0gIlRlc3QgRGF0YSIpICsgZ2d0aXRsZSgiRHJ5IEZvb2QgRm9yZWNhc3QgZnJvbSBMb2cgVHJhbnNmb3JtZWQgRGF0YSIrIAogICN5bGFiKCJEcnkgRm9vZHMiKQoKZHJ5Zm9vZF9tb2RlbDIlPiVmb3JlY2FzdChoPTEyKSU+JWF1dG9wbG90KCkrCiAgYXV0b2xheWVyKGRyeWZvb2RfdGVzdCxzZXJpZXMgPSAiVGVzdCBEYXRhIikgKyBnZ3RpdGxlKCJEcnkgRm9vZHMgRm9yZWNhc3QgZnJvbSBPcmlnaW5hbCBEYXRhIikgKyAKICB5bGFiKCJEcnkgRm9vZHMiKQoKYGBgCgpgYGB7cixmaWcud2lkdGg9Ni41LGZpZy5oZWlnaHQ9My41LHJlc3VsdHM9J2hpZGUnLGZpZy5zaG93PSdob2xkJyxlY2hvPUZBTFNFfQoKI3dldGZvb2RfbW9kZWwlPiVmb3JlY2FzdChoPTEyKSU+JWF1dG9wbG90KCkrCiAgI2F1dG9sYXllcih3ZXRmb29kX3Rlc3Qsc2VyaWVzID0gIlRlc3QgRGF0YSIpICsgZ2d0aXRsZSgiV2V0IEZvb2QgRm9yZWNhc3QgZnJvbSBMb2cgVHJhbnNmb3JtZWQgI0RhdGEiKSArIHlsYWIoIldldCBGb29kIikKCndldGZvb2RfbW9kZWwyJT4lZm9yZWNhc3QoaD0xMiklPiVhdXRvcGxvdCgpKwogIGF1dG9sYXllcih3ZXRmb29kX3Rlc3Qsc2VyaWVzID0gIlRlc3QgRGF0YSIpICsgZ2d0aXRsZSgiV2V0IEZvb2RzIEZvcmVjYXN0IGZyb20gT3JpZ2luYWwgRGF0YSIpICsgCiAgeWxhYigiV2V0Rm9vZHMiKQoKYGBgCgpJbiB0aGUgY29udGV4dCBvZiB0aW1lIHNlcmllcyBmb3JlY2FzdGluZywgdGhlIHN0YXRlbWVudCBzdWdnZXN0cyB0aGF0IGFmdGVyIGFwcGx5aW5nIGEgbG9nIHRyYW5zZm9ybWF0aW9uIHRvIHRoZSBmb3JlY2FzdGVkIGRhdGEgZm9yIGJvdGggd2V0IGZvb2RzIGFuZCBkcnkgZm9vZHMsIHRoZSByZXN1bHRpbmcgcHJlZGljdGlvbiBsaW5lIGluIGJsdWUgY2xvc2VseSBmb2xsb3dzIHRoZSBhY3R1YWwgbGluZSBpbiBvcmFuZ2UuIFRoaXMgaW5kaWNhdGVzIHRoYXQgdGhlIGxvZy10cmFuc2Zvcm1lZCBwcmVkaWN0aW9ucyBhbGlnbiB3ZWxsIHdpdGggdGhlIGFjdHVhbCB2YWx1ZXMgZnJvbSB0aGUgb3JpZ2luYWwgZGF0YS4KClxuZXdwYWdlCiMgRGF0YSBUcmFuc2Zvcm1hdGlvbiBhbmQgTXlTUUwgSW50ZWdyYXRpb24KCkFmdGVyIGZpbmlzaGluZyB0aGUgZm9yZWNhc3RpbmcgcHJvY2VzcywgbW92aW5nIHRoZSBkYXRhIHRvIGEgTXlTUUwgZGF0YWJhc2UgYW5kIHJ1bm5pbmcgc3BlY2lmaWMgcXVlcmllcyBiZWNvbWUgcmVhbGx5IGltcG9ydGFudC4gVGhpcyBoZWxwcyBhIGxvdCBpbiBtYWtpbmcgc21hcnQgZGVjaXNpb25zIGZvciBwbGFubmluZyBhbmQgYWxsb2NhdGluZyByZXNvdXJjZXMgc3RyYXRlZ2ljYWxseS4gVGhpcyBzdGVwIGFsbG93cyB1cyB0byBtZXJnZSB0aGUgZm9yZWNhc3RlZCBkYXRhIGludG8gYSB3ZWxsLW9yZ2FuaXplZCBkYXRhYmFzZS4gSXQgY3JlYXRlcyBhIGNlbnRyYWwgcGxhY2UgZm9yIGluZm9ybWF0aW9uLCBtYWtpbmcgaXQgZWFzaWVyIHRvIG1hbmFnZSBhbmQgYWNjZXNzLiBUaGlzIGFwcHJvYWNoIG5vdCBvbmx5IGltcHJvdmVzIGhvdyB3ZSBhY2Nlc3MgaW5mb3JtYXRpb24gYnV0IGFsc28gaGVscHMgaW4gbWFpbnRhaW5pbmcgdGhlIGRhdGFiYXNlIGVmZmljaWVudGx5LCBtYWtpbmcgZGVjaXNpb24gc3VwcG9ydCBzeXN0ZW1zIHdvcmsgYmV0dGVyLgoKIyMgTXlTUUwgRGF0YWJhc2UgYW5kIFF1ZXJ5CgpNeVNRTCBpcyBhbiBvcGVuLXNvdXJjZSByZWxhdGlvbmFsIGRhdGFiYXNlIG1hbmFnZW1lbnQgc3lzdGVtIHRoYXQgaXMgd2lkZWx5IHVzZWQgZm9yIG1hbmFnaW5nIGFuZCBvcmdhbml6aW5nIHN0cnVjdHVyZWQgZGF0YSBAbXlzcWwuIEl0IGlzIG9uZSBvZiB0aGUgbW9zdCBwb3B1bGFyIGRhdGFiYXNlcyBhbmQgaXMgY29tbW9ubHkgdXNlZCBmb3IgdmFyaW91cyBhcHBsaWNhdGlvbnMsIHJhbmdpbmcgZnJvbSBzbWFsbC1zY2FsZSB3ZWJzaXRlcyB0byBsYXJnZSBlbnRlcnByaXNlIHN5c3RlbXMuCgpNeVNRTCB3aWxsIGFjdCBhcyBhIHJlbGlhYmxlIGFuZCBzY2FsYWJsZSBiYWNrZW5kIGRhdGFiYXNlIGZvciB0aGlzIHByb2plY3QsIGJ5IHByb3ZpZGluZyBlc3NlbnRpYWwgY2FwYWJpbGl0aWVzIGZvciBlZmZpY2llbnRseSBzdG9yaW5nLCBvcmdhbml6aW5nLCBxdWVyeWluZywgYW5kIGludGVncmF0aW5nIGRhdGEuIEJlbG93IEkgYW0gZ29pbmcgdG8gcHJvdmlkZSBzb21lIGV4YW1wbGUgbGx1c3RyYXRpbmcgaG93IHNwZWNpZmljIGFuc3dlcnMgY2FuIGJlIG9idGFpbmVkIHRocm91Z2ggU1FMIHF1ZXJpZXMuCgotIElkZW50aWZ5aW5nIFVuZGVyc2VydmVkIFppcCBDb2RlIEFyZWFzOgoKYGBge3IsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iMTAwJSJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIvVXNlcnMvc2hhbWltYS9EZXNrdG9wL1Byb2plY3RfMS9pbWFnZXMvUGljdHVyZTEucG5nIiwgZXJyb3IgPSBGQUxTRSkKCmBgYAoKCkJ5IGFuYWx5emluZyB0aGUgZGF0YSwgdGhlIG9yZ2FuaXphdGlvbiBjYW4gcGlucG9pbnQgemlwIGNvZGUgYXJlYXMgdGhhdCBhcmUgdW5kZXJzZXJ2ZWQgaW4gdGVybXMgb2YgcGV0IGZvb2QgZGVtYW5kLiBUaGlzIGluZm9ybWF0aW9uIGlzIHZhbHVhYmxlIGZvciBkaXJlY3Rpbmcgb3V0cmVhY2ggZWZmb3J0cyBhbmQgZW5zdXJpbmcgdGhhdCByZXNvdXJjZXMgYXJlIGFsbG9jYXRlZCB0byBhcmVhcyB3aXRoIHRoZSBncmVhdGVzdCBuZWVkLgoKXG5ld3BhZ2UKLSBBbmFseXppbmcgRm9vZHMgRGVtYW5kIGJ5IFBldCBUeXBlIGFuZCBEaXN0cmlidXRpb24gQXJlYXM6CmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjEwMCUifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiL1VzZXJzL3NoYW1pbWEvRGVza3RvcC9Qcm9qZWN0XzEvaW1hZ2VzL1BpY3R1cmUyLnBuZyIsIGVycm9yID0gRkFMU0UpCgpgYGAKVGhlIGRhdGEgYW5hbHlzaXMgYWxsb3dzIGZvciBhIGRldGFpbGVkIGV4YW1pbmF0aW9uIG9mIHBldCBmb29kIGRlbWFuZCBjYXRlZ29yaXplZCBieSBwZXQgdHlwZS4gVGhpcyBpbnNpZ2h0IGhlbHBzIHRoZSBvcmdhbml6YXRpb24gdW5kZXJzdGFuZCB0aGUgdmFyeWluZyBuZWVkcyBvZiBkaWZmZXJlbnQgdHlwZXMgb2YgcGV0cyBhbmQgc3RyYXRlZ2ljYWxseSBwbGFuIGZvb2QgZGlzdHJpYnV0aW9uIGluIHNwZWNpZmljIGFyZWFzLgoKLSBJZGVudGlmeWluZyBIaWdoZXN0IE5lZWQgQXJlYXMgYnkgTnVtYmVyIG9mIFBldHM6CgpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSIxMDAlIn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi9Vc2Vycy9zaGFtaW1hL0Rlc2t0b3AvUHJvamVjdF8xL2ltYWdlcy9QaWN0dXJlMy5wbmciLCBlcnJvciA9IEZBTFNFKQoKYGBgClRoZSBkYXRhIHdpbGwgcmV2ZWFsIGFyZWFzIHdpdGggdGhlIGhpZ2hlc3QgY29uY2VudHJhdGlvbiBvZiBwZXRzLCBpbmRpY2F0aW5nIHJlZ2lvbnMgd2hlcmUgdGhlIGRlbWFuZCBmb3IgcGV0IGZvb2QgaXMgcGFydGljdWxhcmx5IGhpZ2guIFRoaXMga25vd2xlZGdlIGlzIGVzc2VudGlhbCBmb3IgcHJpb3JpdGl6aW5nIGVmZm9ydHMgYW5kIHJlc291cmNlcyB0byBhZGRyZXNzIHRoZSBuZWVkcyBvZiBjb21tdW5pdGllcyB3aXRoIGEgbGFyZ2VyIG51bWJlciBvZiBwZXRzLgpJbiBzdW1tYXJ5LCB0aGUgb3V0Y29tZXMgb2YgdGhpcyBhbmFseXNpcyB3aWxsIHByb3ZpZGUgYSBjb21wcmVoZW5zaXZlIHZpZXcgb2YgdGhlIG9yZ2FuaXphdGlvbidzIG9wZXJhdGlvbmFsIGxhbmRzY2FwZSwgZW5hYmxpbmcgdGFyZ2V0ZWQgaW50ZXJ2ZW50aW9ucyBhbmQgc3RyYXRlZ2ljIGRlY2lzaW9ucyB0byBhZGRyZXNzIHNwZWNpZmljIG5lZWRzIGluIGRpZmZlcmVudCBhcmVhcy4KCkluIHN1bW1hcnksIHRoZSBvdXRjb21lcyBvZiB0aGlzIGFuYWx5c2lzIHdpbGwgcHJvdmlkZSBhIGNvbXByZWhlbnNpdmUgdmlldyBvZiB0aGUgb3JnYW5pemF0aW9uJ3Mgb3BlcmF0aW9uYWwgbGFuZHNjYXBlLCBlbmFibGluZyB0YXJnZXRlZCBpbnRlcnZlbnRpb25zIGFuZCBzdHJhdGVnaWMgZGVjaXNpb25zIHRvIGFkZHJlc3Mgc3BlY2lmaWMgbmVlZHMgaW4gZGlmZmVyZW50IGFyZWFzLgoKIyBMaW1pdGF0aW9ucwoKVGhlIHByZWNpc2lvbiBvZiB0aGUgZm9yZWNhc3RpbmcgbW9kZWxzIHJlbGllcyBzaWduaWZpY2FudGx5IG9uIHRoZSBxdWFsaXR5IG9mIHRoZSBpbnB1dCBkYXRhLiBJbiB0aGlzIHByb2plY3QsIHRoZSBoaXN0b3JpY2FsIGRhdGEgcHJlc2VudHMgY2hhbGxlbmdlcyB3aXRoIGluYWNjdXJhY2llcyBhbmQgbWlzc2luZyB2YWx1ZXMsIHBvdGVudGlhbGx5IGFmZmVjdGluZyB0aGUgZGVwZW5kYWJpbGl0eSBvZiBteSBmb3JlY2FzdHMuIFRoZSBoaXN0b3JpY2FsIGRhdGEgYXZhaWxhYmlsaXR5LCBwYXJ0aWN1bGFybHkgaW4gdGhlIGVhcmx5IHllYXJzLCBpcyBjb25zdHJhaW5lZCwgcG9zaW5nIGh1cmRsZXMgZm9yIHRoZSBmb3JlY2FzdGluZyBtb2RlbHMuIEFkZGl0aW9uYWxseSwgdGhlc2UgbW9kZWxzIG1heSBzdHJ1Z2dsZSB0byBmdWxseSBhY2NvdW50IGZvciBleHRlcm5hbCBmYWN0b3JzIGxpa2Ugc2hpZnRzIGluIGVjb25vbWljIGNvbmRpdGlvbnMsIHB1YmxpYyBoZWFsdGggY3Jpc2VzLCBvciB1bmV4cGVjdGVkIGV2ZW50cyB0aGF0IGNvdWxkIHNpZ25pZmljYW50bHkgaW5mbHVlbmNlIHRoZSBkZW1hbmQgZm9yIHBldCBmb29kLgoKIyBGdXR1cmUgUmVzZWFyY2ggQXJlYXMKCmltcGxlbWVudGluZyB0aGUgc3RvcmFnZSBhbmQgcmV0cmlldmFsIG9mIGRhdGEgaW4gYSBNeVNRTCBkYXRhYmFzZSBpbnZvbHZlcyBjcmVhdGluZyB0YWJsZXMgd2l0aCB1bmlxdWUgaWRlbnRpZmllcnMgZm9yIGN1c3RvbWVycyBhbmQgb3JkZXIgZGV0YWlscy4gVGhpcyBzdGVwIGVuaGFuY2VzIGRhdGEgb3JnYW5pemF0aW9uIGFuZCBhY2Nlc3NpYmlsaXR5LCBsYXlpbmcgdGhlIGZvdW5kYXRpb24gZm9yIG1vcmUgaW4tZGVwdGggYW5hbHlzZXMgYW5kIGltcHJvdmVkIGRhdGEgbWFuYWdlbWVudC4gCkFkZGl0aW9uYWxseSwgZGlmZmVyZW50aWF0aW5nIGZvcmVjYXN0aW5nIG1vZGVscyBmb3Igc3BlY2lmaWMgcGV0IHR5cGVzLCBzdWNoIGFzIGNhdHMgb3IgZG9ncywgY291bGQgb2ZmZXIgbW9yZSBkZXRhaWxlZCBpbnNpZ2h0cyBpbnRvIHRoZSBkZW1hbmQgcGF0dGVybnMgd2l0aGluIGVhY2ggY2F0ZWdvcnkuIFRoaXMgYXBwcm9hY2ggYWxsb3dzIGZvciBhIG1vcmUgbnVhbmNlZCB1bmRlcnN0YW5kaW5nIG9mIHRoZSB1bmlxdWUgZmFjdG9ycyBpbmZsdWVuY2luZyB0aGUgZGVtYW5kIGZvciBkaWZmZXJlbnQgdHlwZXMgb2YgcGV0cy4KCiMgQ29uY2x1c2lvbnMKClRoaXMgcHJvamVjdCBoYXMgYmVlbiBhIGR5bmFtaWMgam91cm5leSwgbmF2aWdhdGluZyB0aGUgaW50cmljYWNpZXMgb2YgZGF0YSBhbmFseXNpcywgbW9kZWxpbmcsIGFuZCBkZWNpc2lvbi1tYWtpbmcuIFRoZSBlbmRlYXZvciB0byB1bnJhdmVsIHBhdHRlcm5zIGFuZCBhbnRpY2lwYXRlIHRyZW5kcyBpbiBwZXQgZm9vZCBkZW1hbmQgaGFzIGJlZW4gZHJpdmVuIGJ5IGEgbWV0aWN1bG91cyBleGFtaW5hdGlvbiBvZiBoaXN0b3JpY2FsIGRhdGEgYW5kIHRoZSBpbXBsZW1lbnRhdGlvbiBvZiByb2J1c3QgZm9yZWNhc3RpbmcgbW9kZWxzLgpUaGUgcHJvamVjdCBub3Qgb25seSBhZHZhbmNlcyB0aGUgdW5kZXJzdGFuZGluZyBvZiBkZW1hbmQgZm9yZWNhc3RpbmcgaW4gdGhlIHBldCBmb29kIGluZHVzdHJ5IGJ1dCBhbHNvIHNldHMgdGhlIHN0YWdlIGZvciBjb250aW51ZWQgcmVzZWFyY2ggYW5kIHJlZmluZW1lbnQuIFRoZSBpbnRlZ3JhdGlvbiBvZiBNWVNRTCBkYXRhIHRyYW5zZm9ybWF0aW9uIG5vdCBvbmx5IGVuaGFuY2VzIHRoZSByZWxpYWJpbGl0eSBvZiB0aGUgYW5hbHlzZXMgYnV0IG9wZW5zIGF2ZW51ZXMgZm9yIG1vcmUgc3BlY2lmaWMgcXVlc3Rpb25zIGFuZCBhbnN3ZXJzLiBCeSBkZWx2aW5nIGludG8gcGV0IGZvb2QgZGVtYW5kIHdpdGggYSBmaW5lciBsZW5zLCB0aGF0IGNhbiB1bmNvdmVyIG51YW5jZXMgdGhhdCB3ZXJlIHByZXZpb3VzbHkgb2JzY3VyZWQuCgpUaGlzIHByb2plY3Qgd2lsbCBlbXBvd2VyIHRoZSBvcmdhbml6YXRpb24gdG8gYWRlcHRseSBjb21wcmVoZW5kIGFuZCBvdmVyc2VlIGl0cyBwZXQgZm9vZCBiYW5rLiBUaGUgZGFzaGJvYXJkIGVtZXJnZXMgYXMgYW4gaW52YWx1YWJsZSB0b29sLCBlc3BlY2lhbGx5IGZvciBmdW5kcmFpc2luZyBhbmQgb3V0cmVhY2ggaW5pdGlhdGl2ZXMsIHBhcnRpY3VsYXJseSBpbiBjb21tdW5pdGllcyB3aXRoIGhpZ2hlciBuZWVkcy4gQWxvbmdzaWRlIHRhcmdldGVkIHF1ZXJpZXMsIGl0IGFkZGl0aW9uYWxseSBlbmhhbmNlcyB0aGUgY2FwYWNpdHkgZm9yIGluZm9ybWVkIGRlY2lzaW9uLW1ha2luZyBpbiBzdHJhdGVnaWMgcGxhbm5pbmcgYW5kIHJlc291cmNlIGFsbG9jYXRpb24uCgoKXG5ld3BhZ2UKCiMgQmlibGlvZ3JhcGh5CgoK
Comments
The results of our t-test provide strong statistical evidence that there is a significant difference in sleep quality between individuals who use smartphones before bedtime and those who do not. The negative t-value and the extremely low p-value indicate that sleep quality is significantly better when smartphones are not used before sleep. Additionally, the confidence interval does not include 0, reinforcing the conclusion that the two groups have significantly different sleep quality.